summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsergiocarlos <carloschilazo@gmail.com>2015-12-08 18:32:49 -0600
committerdormando <dormando@rydia.net>2016-05-28 23:40:07 -0700
commit6895d23e48c6359402066a74c812b3f14be05100 (patch)
tree4eecbe1d9fd15fac04239464f46d2363a72bb427
parent1b13a586624e8e315f23a482691c9bfb3ab36d9b (diff)
downloadmemcached-6895d23e48c6359402066a74c812b3f14be05100.tar.gz
Implement get_expired stats
-rw-r--r--doc/protocol.txt2
-rw-r--r--items.c9
-rw-r--r--items.h4
-rw-r--r--memcached.c22
-rw-r--r--memcached.h6
-rwxr-xr-xt/stats.t17
-rw-r--r--thread.c10
7 files changed, 46 insertions, 24 deletions
diff --git a/doc/protocol.txt b/doc/protocol.txt
index 7e72508..eaa3b16 100644
--- a/doc/protocol.txt
+++ b/doc/protocol.txt
@@ -542,6 +542,8 @@ integers separated by a colon (treat this as a floating point number).
| | | and found present |
| get_misses | 64u | Number of items that have been requested |
| | | and not found |
+| get_expired | 64u | Number of items that have been requested |
+| | | but had already expired. |
| delete_misses | 64u | Number of deletions reqs for missing keys |
| delete_hits | 64u | Number of deletion reqs resulting in |
| | | an item being removed. |
diff --git a/items.c b/items.c
index 93c83ba..938d578 100644
--- a/items.c
+++ b/items.c
@@ -659,7 +659,7 @@ void item_stats_sizes(ADD_STAT add_stats, void *c) {
}
/** wrapper around assoc_find which does the lazy expiration logic */
-item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
+item *do_item_get(const char *key, const size_t nkey, const uint32_t hv, conn *c) {
item *it = assoc_find(key, nkey, hv);
if (it != NULL) {
refcount_incr(&it->refcount);
@@ -711,6 +711,9 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
do_item_unlink(it, hv);
do_item_remove(it);
it = NULL;
+ pthread_mutex_lock(&c->thread->stats.mutex);
+ c->thread->stats.get_expired++;
+ pthread_mutex_unlock(&c->thread->stats.mutex);
if (was_found) {
fprintf(stderr, " -nuked by expire");
}
@@ -727,8 +730,8 @@ item *do_item_get(const char *key, const size_t nkey, const uint32_t hv) {
}
item *do_item_touch(const char *key, size_t nkey, uint32_t exptime,
- const uint32_t hv) {
- item *it = do_item_get(key, nkey, hv);
+ const uint32_t hv, conn *c) {
+ item *it = do_item_get(key, nkey, hv, c);
if (it != NULL) {
it->exptime = exptime;
}
diff --git a/items.h b/items.h
index 4e492b4..8add1ef 100644
--- a/items.h
+++ b/items.h
@@ -23,8 +23,8 @@ void item_stats_totals(ADD_STAT add_stats, void *c);
/*@null@*/
void item_stats_sizes(ADD_STAT add_stats, void *c);
-item *do_item_get(const char *key, const size_t nkey, const uint32_t hv);
-item *do_item_touch(const char *key, const size_t nkey, uint32_t exptime, const uint32_t hv);
+item *do_item_get(const char *key, const size_t nkey, const uint32_t hv, conn *c);
+item *do_item_touch(const char *key, const size_t nkey, uint32_t exptime, const uint32_t hv, conn *c);
void item_stats_reset(void);
extern pthread_mutex_t lru_locks[POWER_LARGEST];
diff --git a/memcached.c b/memcached.c
index 07f8ab5..eb5ffd3 100644
--- a/memcached.c
+++ b/memcached.c
@@ -179,6 +179,7 @@ static rel_time_t realtime(const time_t exptime) {
static void stats_init(void) {
stats.curr_items = stats.total_items = stats.curr_conns = stats.total_conns = stats.conn_structs = 0;
stats.get_cmds = stats.set_cmds = stats.get_hits = stats.get_misses = stats.evictions = stats.reclaimed = 0;
+ stats.get_expired = 0;
stats.touch_cmds = stats.touch_misses = stats.touch_hits = stats.rejected_conns = 0;
stats.malloc_fails = 0;
stats.curr_bytes = stats.listen_disabled_num = 0;
@@ -1296,9 +1297,9 @@ static void process_bin_get_or_touch(conn *c) {
protocol_binary_request_touch *t = binary_get_request(c);
time_t exptime = ntohl(t->message.body.expiration);
- it = item_touch(key, nkey, realtime(exptime));
+ it = item_touch(key, nkey, realtime(exptime), c);
} else {
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
}
if (it) {
@@ -2057,7 +2058,7 @@ static void process_bin_update(conn *c) {
/* Avoid stale data persisting in cache because we failed alloc.
* Unacceptable for SET. Anywhere else too? */
if (c->cmd == PROTOCOL_BINARY_CMD_SET) {
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
if (it) {
item_unlink(it);
item_remove(it);
@@ -2207,7 +2208,7 @@ static void process_bin_delete(conn *c) {
stats_prefix_record_delete(key, nkey);
}
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
if (it) {
uint64_t cas = ntohll(req->message.header.request.cas);
if (cas == 0 || cas == ITEM_get_cas(it)) {
@@ -2308,7 +2309,7 @@ static void complete_nread(conn *c) {
*/
enum store_item_type do_store_item(item *it, int comm, conn *c, const uint32_t hv) {
char *key = ITEM_key(it);
- item *old_it = do_item_get(key, it->nkey, hv);
+ item *old_it = do_item_get(key, it->nkey, hv, c);
enum store_item_type stored = NOT_STORED;
item *new_it = NULL;
@@ -2611,6 +2612,7 @@ static void server_stats(ADD_STAT add_stats, conn *c) {
APPEND_STAT("cmd_touch", "%llu", (unsigned long long)thread_stats.touch_cmds);
APPEND_STAT("get_hits", "%llu", (unsigned long long)slab_stats.get_hits);
APPEND_STAT("get_misses", "%llu", (unsigned long long)thread_stats.get_misses);
+ APPEND_STAT("get_expired", "%llu", (unsigned long long)thread_stats.get_expired);
APPEND_STAT("delete_misses", "%llu", (unsigned long long)thread_stats.delete_misses);
APPEND_STAT("delete_hits", "%llu", (unsigned long long)slab_stats.delete_hits);
APPEND_STAT("incr_misses", "%llu", (unsigned long long)thread_stats.incr_misses);
@@ -2907,7 +2909,7 @@ static inline void process_get_command(conn *c, token_t *tokens, size_t ntokens,
return;
}
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
if (settings.detail_enabled) {
stats_prefix_record_get(key, nkey, NULL != it);
}
@@ -3129,7 +3131,7 @@ static void process_update_command(conn *c, token_t *tokens, const size_t ntoken
/* Avoid stale data persisting in cache because we failed alloc.
* Unacceptable for SET. Anywhere else too? */
if (comm == NREAD_SET) {
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
if (it) {
item_unlink(it);
item_remove(it);
@@ -3170,7 +3172,7 @@ static void process_touch_command(conn *c, token_t *tokens, const size_t ntokens
return;
}
- it = item_touch(key, nkey, realtime(exptime_int));
+ it = item_touch(key, nkey, realtime(exptime_int), c);
if (it) {
item_update(it);
pthread_mutex_lock(&c->thread->stats.mutex);
@@ -3259,7 +3261,7 @@ enum delta_result_type do_add_delta(conn *c, const char *key, const size_t nkey,
int res;
item *it;
- it = do_item_get(key, nkey, hv);
+ it = do_item_get(key, nkey, hv, c);
if (!it) {
return DELTA_ITEM_NOT_FOUND;
}
@@ -3378,7 +3380,7 @@ static void process_delete_command(conn *c, token_t *tokens, const size_t ntoken
stats_prefix_record_delete(key, nkey);
}
- it = item_get(key, nkey);
+ it = item_get(key, nkey, c);
if (it) {
MEMCACHED_COMMAND_DELETE(c->sfd, ITEM_key(it), it->nkey);
diff --git a/memcached.h b/memcached.h
index df972f5..e53e642 100644
--- a/memcached.h
+++ b/memcached.h
@@ -238,6 +238,7 @@ struct thread_stats {
pthread_mutex_t mutex;
uint64_t get_cmds;
uint64_t get_misses;
+ uint64_t get_expired;
uint64_t touch_cmds;
uint64_t touch_misses;
uint64_t delete_misses;
@@ -272,6 +273,7 @@ struct stats {
uint64_t touch_cmds;
uint64_t get_hits;
uint64_t get_misses;
+ uint64_t get_expired;
uint64_t touch_hits;
uint64_t touch_misses;
uint64_t evictions;
@@ -583,8 +585,8 @@ conn *conn_from_freelist(void);
bool conn_add_to_freelist(conn *c);
int is_listen_thread(void);
item *item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbytes);
-item *item_get(const char *key, const size_t nkey);
-item *item_touch(const char *key, const size_t nkey, uint32_t exptime);
+item *item_get(const char *key, const size_t nkey, conn *c);
+item *item_touch(const char *key, const size_t nkey, uint32_t exptime, conn *c);
int item_link(item *it);
void item_remove(item *it);
int item_replace(item *it, item *new_it, const uint32_t hv);
diff --git a/t/stats.t b/t/stats.t
index 91df4d6..6234c49 100755
--- a/t/stats.t
+++ b/t/stats.t
@@ -1,7 +1,7 @@
#!/usr/bin/perl
use strict;
-use Test::More tests => 98;
+use Test::More tests => 103;
use FindBin qw($Bin);
use lib "$Bin/lib";
use MemcachedTest;
@@ -30,6 +30,7 @@ my $sock = $server->sock;
## STAT cmd_touch 0
## STAT get_hits 0
## STAT get_misses 0
+## STAT get_expired 0
## STAT delete_misses 0
## STAT delete_hits 0
## STAT incr_misses 0
@@ -71,10 +72,10 @@ my $sock = $server->sock;
my $stats = mem_stats($sock);
# Test number of keys
-is(scalar(keys(%$stats)), 53, "53 stats values");
+is(scalar(keys(%$stats)), 54, "54 stats values");
# Test initial state
-foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses
+foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses get_expired
bytes_written delete_hits delete_misses incr_hits incr_misses decr_hits
decr_misses listen_disabled_num lrutail_reflocked time_in_listen_disabled_us)) {
is($stats->{$key}, 0, "initial $key is zero");
@@ -190,6 +191,7 @@ is(0, $stats->{'cmd_get'});
is(0, $stats->{'cmd_set'});
is(0, $stats->{'get_hits'});
is(0, $stats->{'get_misses'});
+is(0, $stats->{'get_expired'});
is(0, $stats->{'delete_misses'});
is(0, $stats->{'delete_hits'});
is(0, $stats->{'incr_misses'});
@@ -203,6 +205,15 @@ is(0, $stats->{'evictions'});
is(0, $stats->{'reclaimed'});
is(0, $stats->{'lrutail_reflocked'});
+# item expired
+print $sock "set should_expire 0 1 6\r\nfooval\r\n";
+is(scalar <$sock>, "STORED\r\n", "set item to expire");
+sleep(2);
+print $sock "get should_expire\r\n";
+is(scalar <$sock>, "END\r\n", "item not returned");
+my $stats = mem_stats($sock);
+is(1, $stats->{'get_expired'}, "get_expired counter is 1");
+
print $sock "flush_all\r\n";
is(scalar <$sock>, "OK\r\n", "flushed");
diff --git a/thread.c b/thread.c
index 7c56445..0a1a859 100644
--- a/thread.c
+++ b/thread.c
@@ -486,22 +486,22 @@ item *item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbyt
* Returns an item if it hasn't been marked as expired,
* lazy-expiring as needed.
*/
-item *item_get(const char *key, const size_t nkey) {
+item *item_get(const char *key, const size_t nkey, conn *c) {
item *it;
uint32_t hv;
hv = hash(key, nkey);
item_lock(hv);
- it = do_item_get(key, nkey, hv);
+ it = do_item_get(key, nkey, hv, c);
item_unlock(hv);
return it;
}
-item *item_touch(const char *key, size_t nkey, uint32_t exptime) {
+item *item_touch(const char *key, size_t nkey, uint32_t exptime, conn *c) {
item *it;
uint32_t hv;
hv = hash(key, nkey);
item_lock(hv);
- it = do_item_touch(key, nkey, exptime, hv);
+ it = do_item_touch(key, nkey, exptime, hv, c);
item_unlock(hv);
return it;
}
@@ -613,6 +613,7 @@ void threadlocal_stats_reset(void) {
threads[ii].stats.get_cmds = 0;
threads[ii].stats.get_misses = 0;
+ threads[ii].stats.get_expired = 0;
threads[ii].stats.touch_cmds = 0;
threads[ii].stats.touch_misses = 0;
threads[ii].stats.delete_misses = 0;
@@ -653,6 +654,7 @@ void threadlocal_stats_aggregate(struct thread_stats *stats) {
stats->get_cmds += threads[ii].stats.get_cmds;
stats->get_misses += threads[ii].stats.get_misses;
+ stats->get_expired += threads[ii].stats.get_expired;
stats->touch_cmds += threads[ii].stats.touch_cmds;
stats->touch_misses += threads[ii].stats.touch_misses;
stats->delete_misses += threads[ii].stats.delete_misses;