summaryrefslogtreecommitdiff
path: root/memcached.c
diff options
context:
space:
mode:
Diffstat (limited to 'memcached.c')
-rw-r--r--memcached.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/memcached.c b/memcached.c
index f52c32d..8ac4f51 100644
--- a/memcached.c
+++ b/memcached.c
@@ -166,6 +166,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.touch_cmds = stats.touch_misses = 0;
stats.curr_bytes = stats.listen_disabled_num = 0;
stats.accepting_conns = true; /* assuming we start in this state. */
@@ -1178,6 +1179,78 @@ static void complete_update_bin(conn *c) {
c->item = 0;
}
+static void process_bin_touch(conn *c) {
+ item *it;
+
+ protocol_binary_response_get* rsp = (protocol_binary_response_get*)c->wbuf;
+ char* key = binary_get_key(c);
+ size_t nkey = c->binary_header.request.keylen;
+ protocol_binary_request_touch *t = (void *)&c->binary_header;
+ uint32_t exptime = ntohl(t->message.body.expiration);
+
+ if (settings.verbose > 1) {
+ int ii;
+ /* May be GAT/GATQ/etc */
+ fprintf(stderr, "<%d TOUCH ", c->sfd);
+ for (ii = 0; ii < nkey; ++ii) {
+ fprintf(stderr, "%c", key[ii]);
+ }
+ fprintf(stderr, "\n");
+ }
+
+ it = item_touch(key, nkey, exptime);
+
+ if (it) {
+ /* the length has two unnecessary bytes ("\r\n") */
+ uint16_t keylen = 0;
+ uint32_t bodylen = sizeof(rsp->message.body) + (it->nbytes - 2);
+
+ 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);
+
+ MEMCACHED_COMMAND_TOUCH(c->sfd, ITEM_key(it), it->nkey,
+ it->nbytes, ITEM_get_cas(it));
+
+ if (c->cmd == PROTOCOL_BINARY_CMD_TOUCH) {
+ bodylen -= it->nbytes - 2;
+ }
+
+ add_bin_header(c, 0, sizeof(rsp->message.body), keylen, bodylen);
+ rsp->message.header.response.cas = htonll(ITEM_get_cas(it));
+
+ // add the flags
+ rsp->message.body.flags = htonl(strtoul(ITEM_suffix(it), NULL, 10));
+ add_iov(c, &rsp->message.body, sizeof(rsp->message.body));
+
+ /* Add the data minus the CRLF */
+ if (c->cmd != PROTOCOL_BINARY_CMD_TOUCH) {
+ add_iov(c, ITEM_data(it), it->nbytes - 2);
+ }
+ conn_set_state(c, conn_mwrite);
+ /* Remember this command so we can garbage collect it later */
+ c->item = 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);
+
+ MEMCACHED_COMMAND_TOUCH(c->sfd, key, nkey, -1, 0);
+
+ if (c->noreply) {
+ conn_set_state(c, conn_new_cmd);
+ } else {
+ write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, 0);
+ }
+ }
+
+ if (settings.detail_enabled) {
+ stats_prefix_record_get(key, nkey, NULL != it);
+ }
+}
+
static void process_bin_get(conn *c) {
item *it;
@@ -1736,6 +1809,9 @@ static void dispatch_bin_command(conn *c) {
case PROTOCOL_BINARY_CMD_GETKQ:
c->cmd = PROTOCOL_BINARY_CMD_GETK;
break;
+ case PROTOCOL_BINARY_CMD_GATQ:
+ c->cmd = PROTOCOL_BINARY_CMD_GATQ;
+ break;
default:
c->noreply = false;
}
@@ -1837,6 +1913,15 @@ static void dispatch_bin_command(conn *c) {
protocol_error = 1;
}
break;
+ case PROTOCOL_BINARY_CMD_TOUCH:
+ case PROTOCOL_BINARY_CMD_GAT:
+ case PROTOCOL_BINARY_CMD_GATQ:
+ if (extlen == 4 && keylen != 0) {
+ bin_read_key(c, bin_reading_touch_key, 4);
+ } else {
+ protocol_error = 1;
+ }
+ break;
default:
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND, bodylen);
}
@@ -2064,6 +2149,9 @@ static void complete_nread_binary(conn *c) {
case bin_reading_get_key:
process_bin_get(c);
break;
+ case bin_reading_touch_key:
+ process_bin_touch(c);
+ break;
case bin_reading_stat:
process_bin_stat(c);
break;
@@ -2413,6 +2501,7 @@ static void server_stats(ADD_STAT add_stats, conn *c) {
APPEND_STAT("cmd_get", "%llu", (unsigned long long)thread_stats.get_cmds);
APPEND_STAT("cmd_set", "%llu", (unsigned long long)slab_stats.set_cmds);
APPEND_STAT("cmd_flush", "%llu", (unsigned long long)thread_stats.flush_cmds);
+ 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("delete_misses", "%llu", (unsigned long long)thread_stats.delete_misses);
@@ -2424,6 +2513,8 @@ static void server_stats(ADD_STAT add_stats, conn *c) {
APPEND_STAT("cas_misses", "%llu", (unsigned long long)thread_stats.cas_misses);
APPEND_STAT("cas_hits", "%llu", (unsigned long long)slab_stats.cas_hits);
APPEND_STAT("cas_badval", "%llu", (unsigned long long)slab_stats.cas_badval);
+ APPEND_STAT("touch_hits", "%llu", (unsigned long long)slab_stats.touch_hits);
+ APPEND_STAT("touch_misses", "%llu", (unsigned long long)thread_stats.touch_misses);
APPEND_STAT("auth_cmds", "%llu", (unsigned long long)thread_stats.auth_cmds);
APPEND_STAT("auth_errors", "%llu", (unsigned long long)thread_stats.auth_errors);
APPEND_STAT("bytes_read", "%llu", (unsigned long long)thread_stats.bytes_read);