summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2011-09-27 12:56:59 -0700
committerdormando <dormando@rydia.net>2011-09-27 13:01:49 -0700
commit648a07f9abe2affb622f03bfddb65271422f7055 (patch)
treed424efee44709637eaf8e029e64c9d9cab3fbd21
parent62434519d31fd7335164bc3a92f8b60ed5a714c8 (diff)
downloadmemcached-648a07f9abe2affb622f03bfddb65271422f7055.tar.gz
Add an ASCII touch command.
Not doing GAT for now since I'd have to iterate through gat/gats/multigat/etc. If there's demand, we can add it.
-rw-r--r--memcached.c46
-rwxr-xr-xt/touch.t23
2 files changed, 69 insertions, 0 deletions
diff --git a/memcached.c b/memcached.c
index 54d4eb1..f8316c7 100644
--- a/memcached.c
+++ b/memcached.c
@@ -2899,6 +2899,48 @@ static void process_update_command(conn *c, token_t *tokens, const size_t ntoken
conn_set_state(c, conn_nread);
}
+static void process_touch_command(conn *c, token_t *tokens, const size_t ntokens) {
+ char *key;
+ size_t nkey;
+ int32_t exptime_int = 0;
+ item *it;
+
+ assert(c != NULL);
+
+ set_noreply_maybe(c, tokens, ntokens);
+
+ if (tokens[KEY_TOKEN].length > KEY_MAX_LENGTH) {
+ out_string(c, "CLIENT_ERROR bad command line format");
+ return;
+ }
+
+ key = tokens[KEY_TOKEN].value;
+ nkey = tokens[KEY_TOKEN].length;
+
+ if (!safe_strtol(tokens[2].value, &exptime_int)) {
+ out_string(c, "CLIENT_ERROR invalid exptime argument");
+ return;
+ }
+
+ it = item_touch(key, nkey, realtime(exptime_int));
+ if (it) {
+ pthread_mutex_lock(&c->thread->stats.mutex);
+ c->thread->stats.touch_cmds++;
+ c->thread->stats.slab_stats[it->slabs_clsid].touch_hits++;
+ pthread_mutex_unlock(&c->thread->stats.mutex);
+
+ out_string(c, "TOUCHED");
+ item_remove(it);
+ } else {
+ pthread_mutex_lock(&c->thread->stats.mutex);
+ c->thread->stats.touch_cmds++;
+ c->thread->stats.touch_misses++;
+ pthread_mutex_unlock(&c->thread->stats.mutex);
+
+ out_string(c, "NOT_FOUND");
+ }
+}
+
static void process_arithmetic_command(conn *c, token_t *tokens, const size_t ntokens, const bool incr) {
char temp[INCR_MAX_STORAGE_LEN];
uint64_t delta;
@@ -3160,6 +3202,10 @@ static void process_command(conn *c, char *command) {
process_delete_command(c, tokens, ntokens);
+ } else if ((ntokens == 4 || ntokens == 5) && (strcmp(tokens[COMMAND_TOKEN].value, "touch") == 0)) {
+
+ process_touch_command(c, tokens, ntokens);
+
} else if (ntokens >= 2 && (strcmp(tokens[COMMAND_TOKEN].value, "stats") == 0)) {
process_stat(c, tokens, ntokens);
diff --git a/t/touch.t b/t/touch.t
new file mode 100755
index 0000000..dd2eba1
--- /dev/null
+++ b/t/touch.t
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+
+use strict;
+use Test::More tests => 4;
+use FindBin qw($Bin);
+use lib "$Bin/lib";
+use MemcachedTest;
+
+
+my $server = new_memcached();
+my $sock = $server->sock;
+
+# set foo (and should get it)
+print $sock "set foo 0 2 6\r\nfooval\r\n";
+is(scalar <$sock>, "STORED\r\n", "stored foo");
+mem_get_is($sock, "foo", "fooval");
+
+# touch it
+print $sock "touch foo 10\r\n";
+is(scalar <$sock>, "TOUCHED\r\n", "touched foo");
+
+sleep 2;
+mem_get_is($sock, "foo", "fooval");