[patch] test command
Jacob Coby
jcoby at listingbook.com
Tue Feb 15 14:43:04 PST 2005
It seems like it would be nice to be able to test to see if a key is
cached, its flags, how big the data is, and when it expires. I needed
the extension to make memcached compatible with our current caching system.
I've attached a patch -u against 1.1.11 to add the "test" command. A
typical "test" response looks something like:
test key [key [...]]
foreach key
on success, print "EXISTS flag size expires"
on failure, print nothing (behavior similar to the "get" command")
print END
set foo 0 600 1
1
STORED
get foo
VALUE foo 0 1
1
END
test foo
EXISTS foo 0 1 1108506400
END
quit
The patch is mostly feature complete, but I expect it to need some
formatting, a protocol version bump, and a nod to me if included ;).
Stats could also use cmd_test, test_hits, test_misses added. I can add
the stats entries no problem if there is interest in this patch.
--
-Jacob
-------------- next part --------------
diff -u memcached-1.1.11/memcached.c memcached-1.1.12/memcached.c
--- memcached-1.1.11/memcached.c Mon Apr 26 17:26:48 2004
+++ memcached-1.1.12/memcached.c Tue Feb 15 17:16:07 2005
@@ -667,7 +667,60 @@
out_string(c, "DELETED");
return;
}
-
+
+ if (strncmp(command, "test ", 5) == 0) {
+
+ char *start = command + 4;
+ char key[251];
+ int next;
+ int i = 0;
+ item *it;
+ time_t now = time(0);
+
+ while(sscanf(start, " %250s%n", key, &next) >= 1) {
+ start+=next;
+ stats.get_cmds++;
+ it = assoc_find(key);
+ if (it && (it->it_flags & ITEM_DELETED)) {
+ it = 0;
+ }
+ if (settings.oldest_live && it &&
+ it->time <= settings.oldest_live) {
+ it = 0;
+ }
+ if (it && it->exptime && it->exptime < now) {
+ item_unlink(it);
+ it = 0;
+ }
+
+ if (it) {
+ stats.get_hits++;
+ it->refcount++;
+ item_update(it);
+ *(c->ilist + i) = it;
+ i++;
+ if (i > c->isize) {
+ c->isize *= 2;
+ c->ilist = realloc(c->ilist, sizeof(item *)*c->isize);
+ }
+ } else stats.get_misses++;
+ }
+ c->icurr = c->ilist;
+ c->ileft = i;
+ c->item_comm = NREAD_TEST;
+
+ if (c->ileft) {
+ c->ipart = 0;
+ c->state = conn_mwrite;
+ c->ibytes = 0;
+ return;
+ } else {
+ out_string(c, "END");
+ return;
+ }
+ }
+
+
if (strncmp(command, "stats", 5) == 0) {
process_stat(c, command);
return;
@@ -1014,14 +1067,17 @@
item *it;
/* we finished a chunk, decide what to do next */
switch (c->ipart) {
- case 1:
+ case 1: /* write out the item data chunk */
it = *(c->icurr);
assert((it->it_flags & ITEM_SLABBED) == 0);
- c->iptr = ITEM_data(it);
- c->ibytes = it->nbytes;
+ /* if we're not in TEST mode, write out the item's data */
+ if(c->item_comm != NREAD_TEST) {
+ c->iptr = ITEM_data(it);
+ c->ibytes = it->nbytes;
+ }
c->ipart = 2;
break;
- case 2:
+ case 2: /* pop the written item off of the list */
it = *(c->icurr);
item_remove(it);
c->ileft--;
@@ -1032,17 +1088,21 @@
c->icurr++;
}
/* FALL THROUGH */
- case 0:
+ case 0: /* generate the header chunk */
it = *(c->icurr);
assert((it->it_flags & ITEM_SLABBED) == 0);
- sprintf(c->ibuf, "VALUE %s %u %u\r\n", ITEM_key(it), it->flags, it->nbytes - 2);
- if (settings.verbose > 1)
+ if(c->item_comm == NREAD_TEST)
+ sprintf(c->ibuf, "EXISTS %s %u %u %u\r\n", ITEM_key(it), it->flags, it->nbytes - 2, it->exptime);
+ else
+ sprintf(c->ibuf, "VALUE %s %u %u\r\n", ITEM_key(it), it->flags, it->nbytes - 2);
+
+ if (settings.verbose > 1)
fprintf(stderr, ">%d sending key %s\n", c->sfd, ITEM_key(it));
c->iptr = c->ibuf;
c->ibytes = strlen(c->iptr);
c->ipart = 1;
break;
- case 3:
+ case 3: /* end of list */
out_string(c, "END");
break;
}
diff -u memcached-1.1.11/memcached.h memcached-1.1.12/memcached.h
--- memcached-1.1.11/memcached.h Mon Apr 26 17:26:48 2004
+++ memcached-1.1.12/memcached.h Tue Feb 15 17:09:10 2005
@@ -77,6 +77,7 @@
#define NREAD_ADD 1
#define NREAD_SET 2
#define NREAD_REPLACE 3
+#define NREAD_TEST 4
typedef struct {
int sfd;
More information about the memcached
mailing list