Skip to content

Commit

Permalink
Fix for flush_all 1-second window bug. You can now do a "set" immedia…
Browse files Browse the repository at this point in the history
…tely

after a "flush_all" without the newly set data getting expired.


git-svn-id: http://code.sixapart.com/svn/memcached/trunk/server@436 b0b603af-a30f-0410-a34e-baf09ae79d0b
  • Loading branch information
Steven Grimm committed Nov 20, 2006
1 parent 4d61639 commit c5944dc
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 15 deletions.
26 changes: 26 additions & 0 deletions items.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,29 @@ char* item_stats_sizes(int *bytes) {
free(histogram);
return buf;
}

/* 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;
}
}
}
}
10 changes: 6 additions & 4 deletions memcached.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,11 @@ void stats_init(void) {
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) {
stats.total_items = stats.total_conns = 0;
Expand Down Expand Up @@ -1155,7 +1155,8 @@ void process_command(conn *c, char *command) {
set_current_time();

if (strcmp(command, "flush_all") == 0) {
settings.oldest_live = current_time;
settings.oldest_live = current_time - 1;
item_flush_expired();
out_string(c, "OK");
return;
}
Expand All @@ -1166,7 +1167,8 @@ void process_command(conn *c, char *command) {
return;
}

settings.oldest_live = realtime(exptime);
settings.oldest_live = realtime(exptime) - 1;
item_flush_expired();
out_string(c, "OK");
return;
}
Expand Down
1 change: 1 addition & 0 deletions memcached.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ int item_replace(item *it, item *new_it);
char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int *bytes);
char *item_stats_sizes(int *bytes);
void item_stats(char *buffer, int buflen);
void item_flush_expired(void);

/* time handling */
void set_current_time (); /* update the global variable holding
Expand Down
16 changes: 5 additions & 11 deletions t/flush-all.t
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -16,18 +16,12 @@ is(scalar <$sock>, "STORED\r\n", "stored foo");
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');
}

sleep 1;
mem_get_is($sock, "foo", undef);
# 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');

# and the other form, specifying a flush_all time...
my $expire = time() + 2;
Expand Down

0 comments on commit c5944dc

Please sign in to comment.