From c75248aa193cf05370213922b9c3c69dca6e1a0c Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja.osipov@gmail.com> Date: Tue, 5 Jul 2011 15:00:10 +0400 Subject: [PATCH] Memcached: keep only the parser in memcached-grammar.rl. We modify memcached code quite often, and asking ragel to regenerate .m from .rl file every time .rl file changed was tiresome both for revision control and for code reviews. Leave in memcached-grammar.rl only memcached_dispsatch(), which is generated by ragel, and everything else move to memcached.m. This should lessen cases when we have to re-generate memcached-grammar.m. This patch doesn't produce any code changes, only moves the code (and cleans up include files at start of memcached.m). --- mod/box/CMakeLists.txt | 5 +- mod/box/memcached-grammar.m | 824 +++++++++++------------------------ mod/box/memcached-grammar.rl | 320 -------------- mod/box/memcached.m | 342 +++++++++++++++ 4 files changed, 598 insertions(+), 893 deletions(-) create mode 100644 mod/box/memcached.m diff --git a/mod/box/CMakeLists.txt b/mod/box/CMakeLists.txt index 6121495860..82d3da9715 100644 --- a/mod/box/CMakeLists.txt +++ b/mod/box/CMakeLists.txt @@ -7,6 +7,9 @@ add_custom_command(OUTPUT ${CMAKE_SOURCE_DIR}/mod/box/memcached-grammar.m set_property(DIRECTORY PROPERTY CLEAN_NO_CUSTOM 1) set_source_files_properties(memcached-grammar.m + PROPERTIES HEADER_FILE_ONLY true) + +set_source_files_properties(memcached.m PROPERTIES COMPILE_FLAGS "-Wno-uninitialized") -tarantool_module("box" index.m box.m memcached-grammar.m) +tarantool_module("box" index.m box.m memcached.m memcached-grammar.m) diff --git a/mod/box/memcached-grammar.m b/mod/box/memcached-grammar.m index 6495325939..63bc26fbf6 100644 --- a/mod/box/memcached-grammar.m +++ b/mod/box/memcached-grammar.m @@ -1,5 +1,5 @@ -#line 1 "mod/box/memcached.rl" +#line 1 "mod/box/memcached-grammar.rl" /* * Copyright (C) 2010, 2011 Mail.RU * Copyright (C) 2010, 2011 Yuriy Vostrikov @@ -26,49 +26,8 @@ * SUCH DAMAGE. */ -#include <stdio.h> -#include <string.h> -#include <stdbool.h> -#include <unistd.h> -#include <stdlib.h> -#include <errcode.h> -#include <salloc.h> -#include <palloc.h> -#include <fiber.h> -#include <util.h> -#include <pickle.h> -#include "say.h" - -#include <tarantool.h> -#include <cfg/tarantool_box_cfg.h> -#include <mod/box/box.h> -#include <stat.h> - - -#define STAT(_) \ - _(MEMC_GET, 1) \ - _(MEMC_GET_MISS, 2) \ - _(MEMC_GET_HIT, 3) \ - _(MEMC_EXPIRED_KEYS, 4) - -ENUM(memcached_stat, STAT); -STRS(memcached_stat, STAT); -int stat_base; - -struct index *memcached_index; - -/* memcached tuple format: - <key, meta, data> */ - -struct meta { - u32 exptime; - u32 flags; - u64 cas; -} __packed__; - - -#line 72 "mod/box/memcached.m" +#line 31 "mod/box/memcached-grammar.m" static const int memcached_start = 1; static const int memcached_first_final = 197; static const int memcached_error = 0; @@ -76,153 +35,7 @@ static const int memcached_error = 0; static const int memcached_en_main = 1; -#line 71 "mod/box/memcached.rl" - - - -static u64 -natoq(const u8 *start, const u8 *end) -{ - u64 num = 0; - while (start < end) - num = num * 10 + (*start++ - '0'); - return num; -} - -static void -store(struct box_txn *txn, void *key, u32 exptime, u32 flags, u32 bytes, u8 *data) -{ - u32 box_flags = BOX_QUIET, cardinality = 4; - static u64 cas = 42; - struct meta m; - - struct tbuf *req = tbuf_alloc(fiber->pool); - - tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); - tbuf_append(req, &box_flags, sizeof(box_flags)); - tbuf_append(req, &cardinality, sizeof(cardinality)); - - tbuf_append_field(req, key); - - m.exptime = exptime; - m.flags = flags; - m.cas = cas++; - write_varint32(req, sizeof(m)); - tbuf_append(req, &m, sizeof(m)); - - char b[43]; - sprintf(b, " %"PRIu32" %"PRIu32"\r\n", flags, bytes); - write_varint32(req, strlen(b)); - tbuf_append(req, b, strlen(b)); - - write_varint32(req, bytes); - tbuf_append(req, data, bytes); - - int key_len = load_varint32(&key); - say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64, - key_len, key_len, (u8 *)key, exptime, flags, cas); - box_process(txn, INSERT, req); /* FIXME: handle RW/RO */ -} - -static void -delete(struct box_txn *txn, void *key) -{ - u32 key_len = 1; - struct tbuf *req = tbuf_alloc(fiber->pool); - - tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); - tbuf_append(req, &key_len, sizeof(key_len)); - tbuf_append_field(req, key); - - box_process(txn, DELETE, req); -} - -static struct box_tuple * -find(void *key) -{ - return memcached_index->find(memcached_index, key); -} - -static struct meta * -meta(struct box_tuple *tuple) -{ - void *field = tuple_field(tuple, 1); - return field + 1; -} - -static bool -expired(struct box_tuple *tuple) -{ - struct meta *m = meta(tuple); - return m->exptime == 0 ? 0 : m->exptime < ev_now(); -} - -static bool -is_numeric(void *field, u32 value_len) -{ - for (int i = 0; i < value_len; i++) - if (*((u8 *)field + i) < '0' || '9' < *((u8 *)field + i)) - return false; - return true; -} - -static struct stats { - u64 total_items; - u32 curr_connections; - u32 total_connections; - u64 cmd_get; - u64 cmd_set; - u64 get_hits; - u64 get_misses; - u64 evictions; - u64 bytes_read; - u64 bytes_written; -} stats; - -static void -print_stats() -{ - u64 bytes_used, items; - struct tbuf *out = tbuf_alloc(fiber->pool); - slab_stat2(&bytes_used, &items); - - tbuf_printf(out, "STAT pid %"PRIu32"\r\n", (u32)getpid()); - tbuf_printf(out, "STAT uptime %"PRIu32"\r\n", (u32)tarantool_uptime()); - tbuf_printf(out, "STAT time %"PRIu32"\r\n", (u32)ev_now()); - tbuf_printf(out, "STAT version 1.2.5 (tarantool/box)\r\n"); - tbuf_printf(out, "STAT pointer_size %"PRI_SZ"\r\n", sizeof(void *)*8); - tbuf_printf(out, "STAT curr_items %"PRIu64"\r\n", items); - tbuf_printf(out, "STAT total_items %"PRIu64"\r\n", stats.total_items); - tbuf_printf(out, "STAT bytes %"PRIu64"\r\n", bytes_used); - tbuf_printf(out, "STAT curr_connections %"PRIu32"\r\n", stats.curr_connections); - tbuf_printf(out, "STAT total_connections %"PRIu32"\r\n", stats.total_connections); - tbuf_printf(out, "STAT connection_structures %"PRIu32"\r\n", stats.curr_connections); /* lie a bit */ - tbuf_printf(out, "STAT cmd_get %"PRIu64"\r\n", stats.cmd_get); - tbuf_printf(out, "STAT cmd_set %"PRIu64"\r\n", stats.cmd_set); - tbuf_printf(out, "STAT get_hits %"PRIu64"\r\n", stats.get_hits); - tbuf_printf(out, "STAT get_misses %"PRIu64"\r\n", stats.get_misses); - tbuf_printf(out, "STAT evictions %"PRIu64"\r\n", stats.evictions); - tbuf_printf(out, "STAT bytes_read %"PRIu64"\r\n", stats.bytes_read); - tbuf_printf(out, "STAT bytes_written %"PRIu64"\r\n", stats.bytes_written); - tbuf_printf(out, "STAT limit_maxbytes %"PRIu64"\r\n", (u64)(cfg.slab_alloc_arena * (1 << 30))); - tbuf_printf(out, "STAT threads 1\r\n"); - tbuf_printf(out, "END\r\n"); - add_iov(out->data, out->len); -} - -static void -flush_all(void *data) -{ - uintptr_t delay = (uintptr_t)data; - fiber_sleep(delay - ev_now()); - khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; - for (khiter_t i = kh_begin(map); i != kh_end(map); i++) { - if (kh_exist(map, i)) { - struct box_tuple *tuple = kh_value(map, i); - meta(tuple)->exptime = 1; - } - } -} +#line 30 "mod/box/memcached-grammar.rl" static int __attribute__((noinline)) @@ -250,32 +63,13 @@ memcached_dispatch(struct box_txn *txn) say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p); -#define STORE \ -do { \ - stats.cmd_set++; \ - if (bytes > (1<<20)) { \ - add_iov("SERVER_ERROR object too large for cache\r\n", 41); \ - } else { \ - @try { \ - store(txn, key, exptime, flags, bytes, data); \ - stats.total_items++; \ - add_iov("STORED\r\n", 8); \ - } \ - @catch (ClientError *e) { \ - add_iov("SERVER_ERROR ", 13); \ - add_iov(e->errmsg, strlen(e->errmsg)); \ - add_iov("\r\n", 2); \ - } \ - } \ -} while (0) - -#line 274 "mod/box/memcached.m" +#line 68 "mod/box/memcached-grammar.m" { cs = memcached_start; } -#line 279 "mod/box/memcached.m" +#line 73 "mod/box/memcached-grammar.m" { if ( p == pe ) goto _test_eof; @@ -333,7 +127,7 @@ case 5: goto st0; goto tr15; tr15: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -350,7 +144,7 @@ st6: if ( ++p == pe ) goto _test_eof6; case 6: -#line 354 "mod/box/memcached.m" +#line 148 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st7; goto st0; @@ -364,49 +158,49 @@ case 7: goto tr17; goto st0; tr17: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st8; st8: if ( ++p == pe ) goto _test_eof8; case 8: -#line 375 "mod/box/memcached.m" +#line 169 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr18; if ( 48 <= (*p) && (*p) <= 57 ) goto st8; goto st0; tr18: -#line 517 "mod/box/memcached.rl" +#line 311 "mod/box/memcached-grammar.rl" {flags = natoq(fstart, p);} goto st9; st9: if ( ++p == pe ) goto _test_eof9; case 9: -#line 389 "mod/box/memcached.m" +#line 183 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st9; if ( 48 <= (*p) && (*p) <= 57 ) goto tr21; goto st0; tr21: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st10; st10: if ( ++p == pe ) goto _test_eof10; case 10: -#line 403 "mod/box/memcached.m" +#line 197 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr22; if ( 48 <= (*p) && (*p) <= 57 ) goto st10; goto st0; tr22: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -417,21 +211,21 @@ st11: if ( ++p == pe ) goto _test_eof11; case 11: -#line 421 "mod/box/memcached.m" +#line 215 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st11; if ( 48 <= (*p) && (*p) <= 57 ) goto tr25; goto st0; tr25: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st12; st12: if ( ++p == pe ) goto _test_eof12; case 12: -#line 435 "mod/box/memcached.m" +#line 229 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr26; case 13: goto tr27; @@ -441,11 +235,11 @@ case 12: goto st12; goto st0; tr26: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -466,13 +260,13 @@ tr26: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 269 "mod/box/memcached.rl" +#line 63 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -483,9 +277,9 @@ tr26: } goto st197; tr30: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -506,13 +300,13 @@ tr30: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 269 "mod/box/memcached.rl" +#line 63 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -523,11 +317,11 @@ tr30: } goto st197; tr39: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -548,13 +342,13 @@ tr39: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 269 "mod/box/memcached.rl" +#line 63 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -565,11 +359,11 @@ tr39: } goto st197; tr58: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -590,13 +384,13 @@ tr58: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 298 "mod/box/memcached.rl" +#line 92 "mod/box/memcached-grammar.rl" { struct tbuf *b; void *value; @@ -625,9 +419,9 @@ tr58: } goto st197; tr62: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -648,13 +442,13 @@ tr62: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 298 "mod/box/memcached.rl" +#line 92 "mod/box/memcached-grammar.rl" { struct tbuf *b; void *value; @@ -683,11 +477,11 @@ tr62: } goto st197; tr71: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -708,13 +502,13 @@ tr71: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 298 "mod/box/memcached.rl" +#line 92 "mod/box/memcached-grammar.rl" { struct tbuf *b; void *value; @@ -743,11 +537,11 @@ tr71: } goto st197; tr91: -#line 519 "mod/box/memcached.rl" +#line 313 "mod/box/memcached-grammar.rl" {cas = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -768,13 +562,13 @@ tr91: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 287 "mod/box/memcached.rl" +#line 81 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -787,9 +581,9 @@ tr91: } goto st197; tr95: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -810,13 +604,13 @@ tr95: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 287 "mod/box/memcached.rl" +#line 81 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -829,11 +623,11 @@ tr95: } goto st197; tr105: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -854,13 +648,13 @@ tr105: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 287 "mod/box/memcached.rl" +#line 81 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -873,17 +667,17 @@ tr105: } goto st197; tr118: -#line 520 "mod/box/memcached.rl" +#line 314 "mod/box/memcached-grammar.rl" {incr = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 325 "mod/box/memcached.rl" +#line 119 "mod/box/memcached-grammar.rl" { struct meta *m; struct tbuf *b; @@ -940,15 +734,15 @@ tr118: } goto st197; tr122: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 325 "mod/box/memcached.rl" +#line 119 "mod/box/memcached-grammar.rl" { struct meta *m; struct tbuf *b; @@ -1005,17 +799,17 @@ tr122: } goto st197; tr132: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 325 "mod/box/memcached.rl" +#line 119 "mod/box/memcached-grammar.rl" { struct meta *m; struct tbuf *b; @@ -1072,15 +866,15 @@ tr132: } goto st197; tr141: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 380 "mod/box/memcached.rl" +#line 174 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1100,21 +894,21 @@ tr141: } goto st197; tr146: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) exptime = exptime + ev_now(); } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 380 "mod/box/memcached.rl" +#line 174 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1134,17 +928,17 @@ tr146: } goto st197; tr157: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 380 "mod/box/memcached.rl" +#line 174 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1164,15 +958,15 @@ tr157: } goto st197; tr169: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 475 "mod/box/memcached.rl" +#line 269 "mod/box/memcached-grammar.rl" { if (flush_delay > 0) { struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay); @@ -1184,17 +978,17 @@ tr169: } goto st197; tr174: -#line 521 "mod/box/memcached.rl" +#line 315 "mod/box/memcached-grammar.rl" {flush_delay = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 475 "mod/box/memcached.rl" +#line 269 "mod/box/memcached-grammar.rl" { if (flush_delay > 0) { struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay); @@ -1206,17 +1000,17 @@ tr174: } goto st197; tr185: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 475 "mod/box/memcached.rl" +#line 269 "mod/box/memcached-grammar.rl" { if (flush_delay > 0) { struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay); @@ -1228,15 +1022,15 @@ tr185: } goto st197; tr195: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 398 "mod/box/memcached.rl" +#line 192 "mod/box/memcached-grammar.rl" { txn->op = SELECT; fiber_register_cleanup((void *)txn_cleanup, txn); @@ -1315,25 +1109,25 @@ tr195: } goto st197; tr213: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 489 "mod/box/memcached.rl" +#line 283 "mod/box/memcached-grammar.rl" { return 0; } goto st197; tr233: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1354,13 +1148,13 @@ tr233: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 278 "mod/box/memcached.rl" +#line 72 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1371,9 +1165,9 @@ tr233: } goto st197; tr237: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1394,13 +1188,13 @@ tr237: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 278 "mod/box/memcached.rl" +#line 72 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1411,11 +1205,11 @@ tr237: } goto st197; tr246: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1436,13 +1230,13 @@ tr246: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 278 "mod/box/memcached.rl" +#line 72 "mod/box/memcached-grammar.rl" { key = read_field(keys); struct box_tuple *tuple = find(key); @@ -1453,11 +1247,11 @@ tr246: } goto st197; tr263: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1478,22 +1272,22 @@ tr263: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 264 "mod/box/memcached.rl" +#line 58 "mod/box/memcached-grammar.rl" { key = read_field(keys); STORE; } goto st197; tr267: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1514,24 +1308,24 @@ tr267: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 264 "mod/box/memcached.rl" +#line 58 "mod/box/memcached-grammar.rl" { key = read_field(keys); STORE; } goto st197; tr276: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 523 "mod/box/memcached.rl" +#line 317 "mod/box/memcached-grammar.rl" { size_t parsed = p - (u8 *)fiber->rbuf->data; while (fiber->rbuf->len - parsed < bytes + 2) { @@ -1552,28 +1346,28 @@ tr276: goto exit; } } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 264 "mod/box/memcached.rl" +#line 58 "mod/box/memcached-grammar.rl" { key = read_field(keys); STORE; } goto st197; tr281: -#line 550 "mod/box/memcached.rl" +#line 344 "mod/box/memcached-grammar.rl" { p++; } -#line 544 "mod/box/memcached.rl" +#line 338 "mod/box/memcached-grammar.rl" { done = true; stats.bytes_read += p - (u8 *)fiber->rbuf->data; tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data); } -#line 485 "mod/box/memcached.rl" +#line 279 "mod/box/memcached-grammar.rl" { print_stats(); } @@ -1582,33 +1376,33 @@ st197: if ( ++p == pe ) goto _test_eof197; case 197: -#line 1586 "mod/box/memcached.m" +#line 1380 "mod/box/memcached-grammar.m" goto st0; tr27: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st13; tr40: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st13; st13: if ( ++p == pe ) goto _test_eof13; case 13: -#line 1600 "mod/box/memcached.m" +#line 1394 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr30; goto st0; tr28: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st14; st14: if ( ++p == pe ) goto _test_eof14; case 14: -#line 1612 "mod/box/memcached.m" +#line 1406 "mod/box/memcached-grammar.m" switch( (*p) ) { case 32: goto st14; case 110: goto st15; @@ -1701,18 +1495,18 @@ case 26: goto tr45; goto st0; tr45: -#line 558 "mod/box/memcached.rl" +#line 352 "mod/box/memcached-grammar.rl" {append = true; } goto st27; tr209: -#line 559 "mod/box/memcached.rl" +#line 353 "mod/box/memcached-grammar.rl" {append = false;} goto st27; st27: if ( ++p == pe ) goto _test_eof27; case 27: -#line 1716 "mod/box/memcached.m" +#line 1510 "mod/box/memcached-grammar.m" switch( (*p) ) { case 13: goto st0; case 32: goto st27; @@ -1721,7 +1515,7 @@ case 27: goto st0; goto tr46; tr46: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -1738,7 +1532,7 @@ st28: if ( ++p == pe ) goto _test_eof28; case 28: -#line 1742 "mod/box/memcached.m" +#line 1536 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st29; goto st0; @@ -1752,49 +1546,49 @@ case 29: goto tr49; goto st0; tr49: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st30; st30: if ( ++p == pe ) goto _test_eof30; case 30: -#line 1763 "mod/box/memcached.m" +#line 1557 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr50; if ( 48 <= (*p) && (*p) <= 57 ) goto st30; goto st0; tr50: -#line 517 "mod/box/memcached.rl" +#line 311 "mod/box/memcached-grammar.rl" {flags = natoq(fstart, p);} goto st31; st31: if ( ++p == pe ) goto _test_eof31; case 31: -#line 1777 "mod/box/memcached.m" +#line 1571 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st31; if ( 48 <= (*p) && (*p) <= 57 ) goto tr53; goto st0; tr53: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st32; st32: if ( ++p == pe ) goto _test_eof32; case 32: -#line 1791 "mod/box/memcached.m" +#line 1585 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr54; if ( 48 <= (*p) && (*p) <= 57 ) goto st32; goto st0; tr54: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -1805,21 +1599,21 @@ st33: if ( ++p == pe ) goto _test_eof33; case 33: -#line 1809 "mod/box/memcached.m" +#line 1603 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st33; if ( 48 <= (*p) && (*p) <= 57 ) goto tr57; goto st0; tr57: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st34; st34: if ( ++p == pe ) goto _test_eof34; case 34: -#line 1823 "mod/box/memcached.m" +#line 1617 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr58; case 13: goto tr59; @@ -1829,30 +1623,30 @@ case 34: goto st34; goto st0; tr59: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st35; tr72: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st35; st35: if ( ++p == pe ) goto _test_eof35; case 35: -#line 1844 "mod/box/memcached.m" +#line 1638 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr62; goto st0; tr60: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st36; st36: if ( ++p == pe ) goto _test_eof36; case 36: -#line 1856 "mod/box/memcached.m" +#line 1650 "mod/box/memcached-grammar.m" switch( (*p) ) { case 32: goto st36; case 110: goto st37; @@ -1942,7 +1736,7 @@ case 47: goto st0; goto tr76; tr76: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -1959,7 +1753,7 @@ st48: if ( ++p == pe ) goto _test_eof48; case 48: -#line 1963 "mod/box/memcached.m" +#line 1757 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st49; goto st0; @@ -1973,49 +1767,49 @@ case 49: goto tr78; goto st0; tr78: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st50; st50: if ( ++p == pe ) goto _test_eof50; case 50: -#line 1984 "mod/box/memcached.m" +#line 1778 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr79; if ( 48 <= (*p) && (*p) <= 57 ) goto st50; goto st0; tr79: -#line 517 "mod/box/memcached.rl" +#line 311 "mod/box/memcached-grammar.rl" {flags = natoq(fstart, p);} goto st51; st51: if ( ++p == pe ) goto _test_eof51; case 51: -#line 1998 "mod/box/memcached.m" +#line 1792 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st51; if ( 48 <= (*p) && (*p) <= 57 ) goto tr82; goto st0; tr82: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st52; st52: if ( ++p == pe ) goto _test_eof52; case 52: -#line 2012 "mod/box/memcached.m" +#line 1806 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr83; if ( 48 <= (*p) && (*p) <= 57 ) goto st52; goto st0; tr83: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -2026,49 +1820,49 @@ st53: if ( ++p == pe ) goto _test_eof53; case 53: -#line 2030 "mod/box/memcached.m" +#line 1824 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st53; if ( 48 <= (*p) && (*p) <= 57 ) goto tr86; goto st0; tr86: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st54; st54: if ( ++p == pe ) goto _test_eof54; case 54: -#line 2044 "mod/box/memcached.m" +#line 1838 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr87; if ( 48 <= (*p) && (*p) <= 57 ) goto st54; goto st0; tr87: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st55; st55: if ( ++p == pe ) goto _test_eof55; case 55: -#line 2058 "mod/box/memcached.m" +#line 1852 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st55; if ( 48 <= (*p) && (*p) <= 57 ) goto tr90; goto st0; tr90: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st56; st56: if ( ++p == pe ) goto _test_eof56; case 56: -#line 2072 "mod/box/memcached.m" +#line 1866 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr91; case 13: goto tr92; @@ -2078,30 +1872,30 @@ case 56: goto st56; goto st0; tr106: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st57; tr92: -#line 519 "mod/box/memcached.rl" +#line 313 "mod/box/memcached-grammar.rl" {cas = natoq(fstart, p);} goto st57; st57: if ( ++p == pe ) goto _test_eof57; case 57: -#line 2093 "mod/box/memcached.m" +#line 1887 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr95; goto st0; tr93: -#line 519 "mod/box/memcached.rl" +#line 313 "mod/box/memcached-grammar.rl" {cas = natoq(fstart, p);} goto st58; st58: if ( ++p == pe ) goto _test_eof58; case 58: -#line 2105 "mod/box/memcached.m" +#line 1899 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr95; case 13: goto st57; @@ -2162,14 +1956,14 @@ case 65: } goto st0; tr107: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st66; st66: if ( ++p == pe ) goto _test_eof66; case 66: -#line 2173 "mod/box/memcached.m" +#line 1967 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr95; case 13: goto st57; @@ -2207,18 +2001,18 @@ case 70: goto tr113; goto st0; tr113: -#line 567 "mod/box/memcached.rl" +#line 361 "mod/box/memcached-grammar.rl" {incr_sign = -1;} goto st71; tr202: -#line 566 "mod/box/memcached.rl" +#line 360 "mod/box/memcached-grammar.rl" {incr_sign = 1; } goto st71; st71: if ( ++p == pe ) goto _test_eof71; case 71: -#line 2222 "mod/box/memcached.m" +#line 2016 "mod/box/memcached-grammar.m" switch( (*p) ) { case 13: goto st0; case 32: goto st71; @@ -2227,7 +2021,7 @@ case 71: goto st0; goto tr114; tr114: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -2244,7 +2038,7 @@ st72: if ( ++p == pe ) goto _test_eof72; case 72: -#line 2248 "mod/box/memcached.m" +#line 2042 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st73; goto st0; @@ -2258,14 +2052,14 @@ case 73: goto tr117; goto st0; tr117: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st74; st74: if ( ++p == pe ) goto _test_eof74; case 74: -#line 2269 "mod/box/memcached.m" +#line 2063 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr118; case 13: goto tr119; @@ -2275,30 +2069,30 @@ case 74: goto st74; goto st0; tr133: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st75; tr119: -#line 520 "mod/box/memcached.rl" +#line 314 "mod/box/memcached-grammar.rl" {incr = natoq(fstart, p);} goto st75; st75: if ( ++p == pe ) goto _test_eof75; case 75: -#line 2290 "mod/box/memcached.m" +#line 2084 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr122; goto st0; tr120: -#line 520 "mod/box/memcached.rl" +#line 314 "mod/box/memcached-grammar.rl" {incr = natoq(fstart, p);} goto st76; st76: if ( ++p == pe ) goto _test_eof76; case 76: -#line 2302 "mod/box/memcached.m" +#line 2096 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr122; case 13: goto st75; @@ -2359,14 +2153,14 @@ case 83: } goto st0; tr134: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st84; st84: if ( ++p == pe ) goto _test_eof84; case 84: -#line 2370 "mod/box/memcached.m" +#line 2164 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr122; case 13: goto st75; @@ -2413,7 +2207,7 @@ case 89: goto st0; goto tr140; tr140: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -2430,7 +2224,7 @@ st90: if ( ++p == pe ) goto _test_eof90; case 90: -#line 2434 "mod/box/memcached.m" +#line 2228 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr141; case 13: goto st91; @@ -2438,7 +2232,7 @@ case 90: } goto st0; tr147: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -2446,14 +2240,14 @@ tr147: } goto st91; tr158: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st91; st91: if ( ++p == pe ) goto _test_eof91; case 91: -#line 2457 "mod/box/memcached.m" +#line 2251 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr141; goto st0; @@ -2471,14 +2265,14 @@ case 92: goto tr144; goto st0; tr144: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st93; st93: if ( ++p == pe ) goto _test_eof93; case 93: -#line 2482 "mod/box/memcached.m" +#line 2276 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr146; case 13: goto tr147; @@ -2488,7 +2282,7 @@ case 93: goto st93; goto st0; tr148: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -2499,7 +2293,7 @@ st94: if ( ++p == pe ) goto _test_eof94; case 94: -#line 2503 "mod/box/memcached.m" +#line 2297 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr141; case 13: goto st91; @@ -2560,14 +2354,14 @@ case 101: } goto st0; tr159: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st102; st102: if ( ++p == pe ) goto _test_eof102; case 102: -#line 2571 "mod/box/memcached.m" +#line 2365 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr141; case 13: goto st91; @@ -2641,18 +2435,18 @@ case 111: } goto st0; tr186: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st112; tr175: -#line 521 "mod/box/memcached.rl" +#line 315 "mod/box/memcached-grammar.rl" {flush_delay = natoq(fstart, p);} goto st112; st112: if ( ++p == pe ) goto _test_eof112; case 112: -#line 2656 "mod/box/memcached.m" +#line 2450 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr169; goto st0; @@ -2670,14 +2464,14 @@ case 113: goto tr172; goto st0; tr172: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st114; st114: if ( ++p == pe ) goto _test_eof114; case 114: -#line 2681 "mod/box/memcached.m" +#line 2475 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr174; case 13: goto tr175; @@ -2687,14 +2481,14 @@ case 114: goto st114; goto st0; tr176: -#line 521 "mod/box/memcached.rl" +#line 315 "mod/box/memcached-grammar.rl" {flush_delay = natoq(fstart, p);} goto st115; st115: if ( ++p == pe ) goto _test_eof115; case 115: -#line 2698 "mod/box/memcached.m" +#line 2492 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr169; case 13: goto st112; @@ -2755,14 +2549,14 @@ case 122: } goto st0; tr187: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st123; st123: if ( ++p == pe ) goto _test_eof123; case 123: -#line 2766 "mod/box/memcached.m" +#line 2560 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr169; case 13: goto st112; @@ -2793,18 +2587,18 @@ case 126: } goto st0; tr191: -#line 563 "mod/box/memcached.rl" +#line 357 "mod/box/memcached-grammar.rl" {show_cas = false;} goto st127; tr198: -#line 564 "mod/box/memcached.rl" +#line 358 "mod/box/memcached-grammar.rl" {show_cas = true;} goto st127; st127: if ( ++p == pe ) goto _test_eof127; case 127: -#line 2808 "mod/box/memcached.m" +#line 2602 "mod/box/memcached-grammar.m" switch( (*p) ) { case 13: goto st0; case 32: goto st127; @@ -2813,7 +2607,7 @@ case 127: goto st0; goto tr193; tr193: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -2830,7 +2624,7 @@ st128: if ( ++p == pe ) goto _test_eof128; case 128: -#line 2834 "mod/box/memcached.m" +#line 2628 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr195; case 13: goto st129; @@ -3037,7 +2831,7 @@ case 155: goto st0; goto tr222; tr222: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -3054,7 +2848,7 @@ st156: if ( ++p == pe ) goto _test_eof156; case 156: -#line 3058 "mod/box/memcached.m" +#line 2852 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st157; goto st0; @@ -3068,49 +2862,49 @@ case 157: goto tr224; goto st0; tr224: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st158; st158: if ( ++p == pe ) goto _test_eof158; case 158: -#line 3079 "mod/box/memcached.m" +#line 2873 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr225; if ( 48 <= (*p) && (*p) <= 57 ) goto st158; goto st0; tr225: -#line 517 "mod/box/memcached.rl" +#line 311 "mod/box/memcached-grammar.rl" {flags = natoq(fstart, p);} goto st159; st159: if ( ++p == pe ) goto _test_eof159; case 159: -#line 3093 "mod/box/memcached.m" +#line 2887 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st159; if ( 48 <= (*p) && (*p) <= 57 ) goto tr228; goto st0; tr228: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st160; st160: if ( ++p == pe ) goto _test_eof160; case 160: -#line 3107 "mod/box/memcached.m" +#line 2901 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr229; if ( 48 <= (*p) && (*p) <= 57 ) goto st160; goto st0; tr229: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -3121,21 +2915,21 @@ st161: if ( ++p == pe ) goto _test_eof161; case 161: -#line 3125 "mod/box/memcached.m" +#line 2919 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st161; if ( 48 <= (*p) && (*p) <= 57 ) goto tr232; goto st0; tr232: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st162; st162: if ( ++p == pe ) goto _test_eof162; case 162: -#line 3139 "mod/box/memcached.m" +#line 2933 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr233; case 13: goto tr234; @@ -3145,30 +2939,30 @@ case 162: goto st162; goto st0; tr234: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st163; tr247: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st163; st163: if ( ++p == pe ) goto _test_eof163; case 163: -#line 3160 "mod/box/memcached.m" +#line 2954 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr237; goto st0; tr235: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st164; st164: if ( ++p == pe ) goto _test_eof164; case 164: -#line 3172 "mod/box/memcached.m" +#line 2966 "mod/box/memcached-grammar.m" switch( (*p) ) { case 32: goto st164; case 110: goto st165; @@ -3260,7 +3054,7 @@ case 175: goto st0; goto tr252; tr252: -#line 494 "mod/box/memcached.rl" +#line 288 "mod/box/memcached-grammar.rl" { fstart = p; for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++); @@ -3277,7 +3071,7 @@ st176: if ( ++p == pe ) goto _test_eof176; case 176: -#line 3281 "mod/box/memcached.m" +#line 3075 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st177; goto st0; @@ -3291,49 +3085,49 @@ case 177: goto tr254; goto st0; tr254: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st178; st178: if ( ++p == pe ) goto _test_eof178; case 178: -#line 3302 "mod/box/memcached.m" +#line 3096 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr255; if ( 48 <= (*p) && (*p) <= 57 ) goto st178; goto st0; tr255: -#line 517 "mod/box/memcached.rl" +#line 311 "mod/box/memcached-grammar.rl" {flags = natoq(fstart, p);} goto st179; st179: if ( ++p == pe ) goto _test_eof179; case 179: -#line 3316 "mod/box/memcached.m" +#line 3110 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st179; if ( 48 <= (*p) && (*p) <= 57 ) goto tr258; goto st0; tr258: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st180; st180: if ( ++p == pe ) goto _test_eof180; case 180: -#line 3330 "mod/box/memcached.m" +#line 3124 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto tr259; if ( 48 <= (*p) && (*p) <= 57 ) goto st180; goto st0; tr259: -#line 510 "mod/box/memcached.rl" +#line 304 "mod/box/memcached-grammar.rl" { exptime = natoq(fstart, p); if (exptime > 0 && exptime <= 60*60*24*30) @@ -3344,21 +3138,21 @@ st181: if ( ++p == pe ) goto _test_eof181; case 181: -#line 3348 "mod/box/memcached.m" +#line 3142 "mod/box/memcached-grammar.m" if ( (*p) == 32 ) goto st181; if ( 48 <= (*p) && (*p) <= 57 ) goto tr262; goto st0; tr262: -#line 493 "mod/box/memcached.rl" +#line 287 "mod/box/memcached-grammar.rl" { fstart = p; } goto st182; st182: if ( ++p == pe ) goto _test_eof182; case 182: -#line 3362 "mod/box/memcached.m" +#line 3156 "mod/box/memcached-grammar.m" switch( (*p) ) { case 10: goto tr263; case 13: goto tr264; @@ -3368,30 +3162,30 @@ case 182: goto st182; goto st0; tr264: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st183; tr277: -#line 552 "mod/box/memcached.rl" +#line 346 "mod/box/memcached-grammar.rl" { noreply = true; } goto st183; st183: if ( ++p == pe ) goto _test_eof183; case 183: -#line 3383 "mod/box/memcached.m" +#line 3177 "mod/box/memcached-grammar.m" if ( (*p) == 10 ) goto tr267; goto st0; tr265: -#line 518 "mod/box/memcached.rl" +#line 312 "mod/box/memcached-grammar.rl" {bytes = natoq(fstart, p);} goto st184; st184: if ( ++p == pe ) goto _test_eof184; case 184: -#line 3395 "mod/box/memcached.m" +#line 3189 "mod/box/memcached-grammar.m" switch( (*p) ) { case 32: goto st184; case 110: goto st185; @@ -3687,7 +3481,7 @@ case 196: _out: {} } -#line 577 "mod/box/memcached.rl" +#line 371 "mod/box/memcached-grammar.rl" if (!done) { @@ -3716,120 +3510,6 @@ case 196: return 1; } -void -memcached_handler(void *_data __attribute__((unused))) -{ - struct box_txn *txn; - stats.total_connections++; - stats.curr_connections++; - int r, p; - int batch_count; - - for (;;) { - batch_count = 0; - if ((r = fiber_bread(fiber->rbuf, 1)) <= 0) { - say_debug("read returned %i, closing connection", r); - goto exit; - } - - dispatch: - txn = txn_alloc(BOX_QUIET); - p = memcached_dispatch(txn); - if (p < 0) { - say_debug("negative dispatch, closing connection"); - goto exit; - } - - if (p == 0 && batch_count == 0) /* we havn't successfully parsed any requests */ - continue; - - if (p == 1) { - batch_count++; - /* some unparsed commands remain and batch count less than 20 */ - if (fiber->rbuf->len > 0 && batch_count < 20) - goto dispatch; - } - - r = fiber_flush_output(); - if (r < 0) { - say_debug("flush_output failed, closing connection"); - goto exit; - } - - stats.bytes_written += r; - fiber_gc(); - - if (p == 1 && fiber->rbuf->len > 0) { - batch_count = 0; - goto dispatch; - } - } -exit: - fiber_flush_output(); - fiber_sleep(0.01); - say_debug("exit"); - stats.curr_connections--; /* FIXME: nonlocal exit via exception will leak this counter */ -} - -void -memcached_init(void) -{ - stat_base = stat_register(memcached_stat_strs, memcached_stat_MAX); -} - -void -memcached_expire(void *data __attribute__((unused))) -{ - static khiter_t i; - khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; - - say_info("memcached expire fiber started"); - for (;;) { - if (i > kh_end(map)) - i = kh_begin(map); - - struct tbuf *keys_to_delete = tbuf_alloc(fiber->pool); - int expired_keys = 0; - - for (int j = 0; j < cfg.memcached_expire_per_loop; j++, i++) { - if (i == kh_end(map)) { - i = kh_begin(map); - break; - } - - if (!kh_exist(map, i)) - continue; - - struct box_tuple *tuple = kh_value(map, i); - - if (!expired(tuple)) - continue; - - say_debug("expire tuple %p", tuple); - tbuf_append_field(keys_to_delete, tuple->data); - } - - while (keys_to_delete->len > 0) { - struct box_txn *txn = txn_alloc(BOX_QUIET); - @try { - delete(txn, read_field(keys_to_delete)); - expired_keys++; - } - @catch (id e) { - /* The error is already logged. */ - } - } - stat_collect(stat_base, MEMC_EXPIRED_KEYS, expired_keys); - - fiber_gc(); - - double delay = (double)cfg.memcached_expire_per_loop * cfg.memcached_expire_full_sweep / (map->size + 1); - if (delay > 1) - delay = 1; - fiber_sleep(delay); - } -} - /* * Local Variables: * mode: c diff --git a/mod/box/memcached-grammar.rl b/mod/box/memcached-grammar.rl index a698f056f7..76bedfb69f 100644 --- a/mod/box/memcached-grammar.rl +++ b/mod/box/memcached-grammar.rl @@ -24,198 +24,11 @@ * SUCH DAMAGE. */ -#include <stdio.h> -#include <string.h> -#include <stdbool.h> -#include <unistd.h> -#include <stdlib.h> - -#include <errcode.h> -#include <salloc.h> -#include <palloc.h> -#include <fiber.h> -#include <util.h> -#include <pickle.h> -#include "say.h" - -#include <tarantool.h> -#include <cfg/tarantool_box_cfg.h> -#include <mod/box/box.h> -#include <stat.h> - - -#define STAT(_) \ - _(MEMC_GET, 1) \ - _(MEMC_GET_MISS, 2) \ - _(MEMC_GET_HIT, 3) \ - _(MEMC_EXPIRED_KEYS, 4) - -ENUM(memcached_stat, STAT); -STRS(memcached_stat, STAT); -int stat_base; - -struct index *memcached_index; - -/* memcached tuple format: - <key, meta, data> */ - -struct meta { - u32 exptime; - u32 flags; - u64 cas; -} __packed__; - %%{ machine memcached; write data; }%% - -static u64 -natoq(const u8 *start, const u8 *end) -{ - u64 num = 0; - while (start < end) - num = num * 10 + (*start++ - '0'); - return num; -} - -static void -store(struct box_txn *txn, void *key, u32 exptime, u32 flags, u32 bytes, u8 *data) -{ - u32 box_flags = BOX_QUIET, cardinality = 4; - static u64 cas = 42; - struct meta m; - - struct tbuf *req = tbuf_alloc(fiber->pool); - - tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); - tbuf_append(req, &box_flags, sizeof(box_flags)); - tbuf_append(req, &cardinality, sizeof(cardinality)); - - tbuf_append_field(req, key); - - m.exptime = exptime; - m.flags = flags; - m.cas = cas++; - write_varint32(req, sizeof(m)); - tbuf_append(req, &m, sizeof(m)); - - char b[43]; - sprintf(b, " %"PRIu32" %"PRIu32"\r\n", flags, bytes); - write_varint32(req, strlen(b)); - tbuf_append(req, b, strlen(b)); - - write_varint32(req, bytes); - tbuf_append(req, data, bytes); - - int key_len = load_varint32(&key); - say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64, - key_len, key_len, (u8 *)key, exptime, flags, cas); - box_process(txn, INSERT, req); /* FIXME: handle RW/RO */ -} - -static void -delete(struct box_txn *txn, void *key) -{ - u32 key_len = 1; - struct tbuf *req = tbuf_alloc(fiber->pool); - - tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); - tbuf_append(req, &key_len, sizeof(key_len)); - tbuf_append_field(req, key); - - box_process(txn, DELETE, req); -} - -static struct box_tuple * -find(void *key) -{ - return memcached_index->find(memcached_index, key); -} - -static struct meta * -meta(struct box_tuple *tuple) -{ - void *field = tuple_field(tuple, 1); - return field + 1; -} - -static bool -expired(struct box_tuple *tuple) -{ - struct meta *m = meta(tuple); - return m->exptime == 0 ? 0 : m->exptime < ev_now(); -} - -static bool -is_numeric(void *field, u32 value_len) -{ - for (int i = 0; i < value_len; i++) - if (*((u8 *)field + i) < '0' || '9' < *((u8 *)field + i)) - return false; - return true; -} - -static struct stats { - u64 total_items; - u32 curr_connections; - u32 total_connections; - u64 cmd_get; - u64 cmd_set; - u64 get_hits; - u64 get_misses; - u64 evictions; - u64 bytes_read; - u64 bytes_written; -} stats; - -static void -print_stats() -{ - u64 bytes_used, items; - struct tbuf *out = tbuf_alloc(fiber->pool); - slab_stat2(&bytes_used, &items); - - tbuf_printf(out, "STAT pid %"PRIu32"\r\n", (u32)getpid()); - tbuf_printf(out, "STAT uptime %"PRIu32"\r\n", (u32)tarantool_uptime()); - tbuf_printf(out, "STAT time %"PRIu32"\r\n", (u32)ev_now()); - tbuf_printf(out, "STAT version 1.2.5 (tarantool/box)\r\n"); - tbuf_printf(out, "STAT pointer_size %"PRI_SZ"\r\n", sizeof(void *)*8); - tbuf_printf(out, "STAT curr_items %"PRIu64"\r\n", items); - tbuf_printf(out, "STAT total_items %"PRIu64"\r\n", stats.total_items); - tbuf_printf(out, "STAT bytes %"PRIu64"\r\n", bytes_used); - tbuf_printf(out, "STAT curr_connections %"PRIu32"\r\n", stats.curr_connections); - tbuf_printf(out, "STAT total_connections %"PRIu32"\r\n", stats.total_connections); - tbuf_printf(out, "STAT connection_structures %"PRIu32"\r\n", stats.curr_connections); /* lie a bit */ - tbuf_printf(out, "STAT cmd_get %"PRIu64"\r\n", stats.cmd_get); - tbuf_printf(out, "STAT cmd_set %"PRIu64"\r\n", stats.cmd_set); - tbuf_printf(out, "STAT get_hits %"PRIu64"\r\n", stats.get_hits); - tbuf_printf(out, "STAT get_misses %"PRIu64"\r\n", stats.get_misses); - tbuf_printf(out, "STAT evictions %"PRIu64"\r\n", stats.evictions); - tbuf_printf(out, "STAT bytes_read %"PRIu64"\r\n", stats.bytes_read); - tbuf_printf(out, "STAT bytes_written %"PRIu64"\r\n", stats.bytes_written); - tbuf_printf(out, "STAT limit_maxbytes %"PRIu64"\r\n", (u64)(cfg.slab_alloc_arena * (1 << 30))); - tbuf_printf(out, "STAT threads 1\r\n"); - tbuf_printf(out, "END\r\n"); - add_iov(out->data, out->len); -} - -static void -flush_all(void *data) -{ - uintptr_t delay = (uintptr_t)data; - fiber_sleep(delay - ev_now()); - khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; - for (khiter_t i = kh_begin(map); i != kh_end(map); i++) { - if (kh_exist(map, i)) { - struct box_tuple *tuple = kh_value(map, i); - meta(tuple)->exptime = 1; - } - } -} - - static int __attribute__((noinline)) memcached_dispatch(struct box_txn *txn) { @@ -241,25 +54,6 @@ memcached_dispatch(struct box_txn *txn) say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p); -#define STORE \ -do { \ - stats.cmd_set++; \ - if (bytes > (1<<20)) { \ - add_iov("SERVER_ERROR object too large for cache\r\n", 41); \ - } else { \ - @try { \ - store(txn, key, exptime, flags, bytes, data); \ - stats.total_items++; \ - add_iov("STORED\r\n", 8); \ - } \ - @catch (ClientError *e) { \ - add_iov("SERVER_ERROR ", 13); \ - add_iov(e->errmsg, strlen(e->errmsg)); \ - add_iov("\r\n", 2); \ - } \ - } \ -} while (0) - %%{ action set { key = read_field(keys); @@ -602,120 +396,6 @@ do { \ return 1; } -void -memcached_handler(void *_data __attribute__((unused))) -{ - struct box_txn *txn; - stats.total_connections++; - stats.curr_connections++; - int r, p; - int batch_count; - - for (;;) { - batch_count = 0; - if ((r = fiber_bread(fiber->rbuf, 1)) <= 0) { - say_debug("read returned %i, closing connection", r); - goto exit; - } - - dispatch: - txn = txn_alloc(BOX_QUIET); - p = memcached_dispatch(txn); - if (p < 0) { - say_debug("negative dispatch, closing connection"); - goto exit; - } - - if (p == 0 && batch_count == 0) /* we havn't successfully parsed any requests */ - continue; - - if (p == 1) { - batch_count++; - /* some unparsed commands remain and batch count less than 20 */ - if (fiber->rbuf->len > 0 && batch_count < 20) - goto dispatch; - } - - r = fiber_flush_output(); - if (r < 0) { - say_debug("flush_output failed, closing connection"); - goto exit; - } - - stats.bytes_written += r; - fiber_gc(); - - if (p == 1 && fiber->rbuf->len > 0) { - batch_count = 0; - goto dispatch; - } - } -exit: - fiber_flush_output(); - fiber_sleep(0.01); - say_debug("exit"); - stats.curr_connections--; /* FIXME: nonlocal exit via exception will leak this counter */ -} - -void -memcached_init(void) -{ - stat_base = stat_register(memcached_stat_strs, memcached_stat_MAX); -} - -void -memcached_expire(void *data __attribute__((unused))) -{ - static khiter_t i; - khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; - - say_info("memcached expire fiber started"); - for (;;) { - if (i > kh_end(map)) - i = kh_begin(map); - - struct tbuf *keys_to_delete = tbuf_alloc(fiber->pool); - int expired_keys = 0; - - for (int j = 0; j < cfg.memcached_expire_per_loop; j++, i++) { - if (i == kh_end(map)) { - i = kh_begin(map); - break; - } - - if (!kh_exist(map, i)) - continue; - - struct box_tuple *tuple = kh_value(map, i); - - if (!expired(tuple)) - continue; - - say_debug("expire tuple %p", tuple); - tbuf_append_field(keys_to_delete, tuple->data); - } - - while (keys_to_delete->len > 0) { - struct box_txn *txn = txn_alloc(BOX_QUIET); - @try { - delete(txn, read_field(keys_to_delete)); - expired_keys++; - } - @catch (id e) { - /* The error is already logged. */ - } - } - stat_collect(stat_base, MEMC_EXPIRED_KEYS, expired_keys); - - fiber_gc(); - - double delay = (double)cfg.memcached_expire_per_loop * cfg.memcached_expire_full_sweep / (map->size + 1); - if (delay > 1) - delay = 1; - fiber_sleep(delay); - } -} - /* * Local Variables: * mode: c diff --git a/mod/box/memcached.m b/mod/box/memcached.m new file mode 100644 index 0000000000..0643b6d32f --- /dev/null +++ b/mod/box/memcached.m @@ -0,0 +1,342 @@ + +#line 1 "mod/box/memcached.rl" +/* + * Copyright (C) 2010, 2011 Mail.RU + * Copyright (C) 2010, 2011 Yuriy Vostrikov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "tarantool.h" +#include "box.h" +#include "fiber.h" +#include "cfg/warning.h" +#include "cfg/tarantool_box_cfg.h" +#include "say.h" +#include "stat.h" +#include "salloc.h" + +#define STAT(_) \ + _(MEMC_GET, 1) \ + _(MEMC_GET_MISS, 2) \ + _(MEMC_GET_HIT, 3) \ + _(MEMC_EXPIRED_KEYS, 4) + +ENUM(memcached_stat, STAT); +STRS(memcached_stat, STAT); +int stat_base; + +struct index *memcached_index; + +/* memcached tuple format: + <key, meta, data> */ + +struct meta { + u32 exptime; + u32 flags; + u64 cas; +} __packed__; + +static u64 +natoq(const u8 *start, const u8 *end) +{ + u64 num = 0; + while (start < end) + num = num * 10 + (*start++ - '0'); + return num; +} + +static void +store(struct box_txn *txn, void *key, u32 exptime, u32 flags, u32 bytes, u8 *data) +{ + u32 box_flags = BOX_QUIET, cardinality = 4; + static u64 cas = 42; + struct meta m; + + struct tbuf *req = tbuf_alloc(fiber->pool); + + tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); + tbuf_append(req, &box_flags, sizeof(box_flags)); + tbuf_append(req, &cardinality, sizeof(cardinality)); + + tbuf_append_field(req, key); + + m.exptime = exptime; + m.flags = flags; + m.cas = cas++; + write_varint32(req, sizeof(m)); + tbuf_append(req, &m, sizeof(m)); + + char b[43]; + sprintf(b, " %"PRIu32" %"PRIu32"\r\n", flags, bytes); + write_varint32(req, strlen(b)); + tbuf_append(req, b, strlen(b)); + + write_varint32(req, bytes); + tbuf_append(req, data, bytes); + + int key_len = load_varint32(&key); + say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64, + key_len, key_len, (u8 *)key, exptime, flags, cas); + box_process(txn, INSERT, req); /* FIXME: handle RW/RO */ +} + +static void +delete(struct box_txn *txn, void *key) +{ + u32 key_len = 1; + struct tbuf *req = tbuf_alloc(fiber->pool); + + tbuf_append(req, &cfg.memcached_namespace, sizeof(u32)); + tbuf_append(req, &key_len, sizeof(key_len)); + tbuf_append_field(req, key); + + box_process(txn, DELETE, req); +} + +static struct box_tuple * +find(void *key) +{ + return memcached_index->find(memcached_index, key); +} + +static struct meta * +meta(struct box_tuple *tuple) +{ + void *field = tuple_field(tuple, 1); + return field + 1; +} + +static bool +expired(struct box_tuple *tuple) +{ + struct meta *m = meta(tuple); + return m->exptime == 0 ? 0 : m->exptime < ev_now(); +} + +static bool +is_numeric(void *field, u32 value_len) +{ + for (int i = 0; i < value_len; i++) + if (*((u8 *)field + i) < '0' || '9' < *((u8 *)field + i)) + return false; + return true; +} + +static struct stats { + u64 total_items; + u32 curr_connections; + u32 total_connections; + u64 cmd_get; + u64 cmd_set; + u64 get_hits; + u64 get_misses; + u64 evictions; + u64 bytes_read; + u64 bytes_written; +} stats; + +static void +print_stats() +{ + u64 bytes_used, items; + struct tbuf *out = tbuf_alloc(fiber->pool); + slab_stat2(&bytes_used, &items); + + tbuf_printf(out, "STAT pid %"PRIu32"\r\n", (u32)getpid()); + tbuf_printf(out, "STAT uptime %"PRIu32"\r\n", (u32)tarantool_uptime()); + tbuf_printf(out, "STAT time %"PRIu32"\r\n", (u32)ev_now()); + tbuf_printf(out, "STAT version 1.2.5 (tarantool/box)\r\n"); + tbuf_printf(out, "STAT pointer_size %"PRI_SZ"\r\n", sizeof(void *)*8); + tbuf_printf(out, "STAT curr_items %"PRIu64"\r\n", items); + tbuf_printf(out, "STAT total_items %"PRIu64"\r\n", stats.total_items); + tbuf_printf(out, "STAT bytes %"PRIu64"\r\n", bytes_used); + tbuf_printf(out, "STAT curr_connections %"PRIu32"\r\n", stats.curr_connections); + tbuf_printf(out, "STAT total_connections %"PRIu32"\r\n", stats.total_connections); + tbuf_printf(out, "STAT connection_structures %"PRIu32"\r\n", stats.curr_connections); /* lie a bit */ + tbuf_printf(out, "STAT cmd_get %"PRIu64"\r\n", stats.cmd_get); + tbuf_printf(out, "STAT cmd_set %"PRIu64"\r\n", stats.cmd_set); + tbuf_printf(out, "STAT get_hits %"PRIu64"\r\n", stats.get_hits); + tbuf_printf(out, "STAT get_misses %"PRIu64"\r\n", stats.get_misses); + tbuf_printf(out, "STAT evictions %"PRIu64"\r\n", stats.evictions); + tbuf_printf(out, "STAT bytes_read %"PRIu64"\r\n", stats.bytes_read); + tbuf_printf(out, "STAT bytes_written %"PRIu64"\r\n", stats.bytes_written); + tbuf_printf(out, "STAT limit_maxbytes %"PRIu64"\r\n", (u64)(cfg.slab_alloc_arena * (1 << 30))); + tbuf_printf(out, "STAT threads 1\r\n"); + tbuf_printf(out, "END\r\n"); + add_iov(out->data, out->len); +} + +static void +flush_all(void *data) +{ + uintptr_t delay = (uintptr_t)data; + fiber_sleep(delay - ev_now()); + khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; + for (khiter_t i = kh_begin(map); i != kh_end(map); i++) { + if (kh_exist(map, i)) { + struct box_tuple *tuple = kh_value(map, i); + meta(tuple)->exptime = 1; + } + } +} + +#define STORE \ +do { \ + stats.cmd_set++; \ + if (bytes > (1<<20)) { \ + add_iov("SERVER_ERROR object too large for cache\r\n", 41); \ + } else { \ + @try { \ + store(txn, key, exptime, flags, bytes, data); \ + stats.total_items++; \ + add_iov("STORED\r\n", 8); \ + } \ + @catch (ClientError *e) { \ + add_iov("SERVER_ERROR ", 13); \ + add_iov(e->errmsg, strlen(e->errmsg)); \ + add_iov("\r\n", 2); \ + } \ + } \ +} while (0) + +#include "memcached-grammar.m" + +void +memcached_handler(void *_data __attribute__((unused))) +{ + struct box_txn *txn; + stats.total_connections++; + stats.curr_connections++; + int r, p; + int batch_count; + + for (;;) { + batch_count = 0; + if ((r = fiber_bread(fiber->rbuf, 1)) <= 0) { + say_debug("read returned %i, closing connection", r); + goto exit; + } + + dispatch: + txn = txn_alloc(BOX_QUIET); + p = memcached_dispatch(txn); + if (p < 0) { + say_debug("negative dispatch, closing connection"); + goto exit; + } + + if (p == 0 && batch_count == 0) /* we havn't successfully parsed any requests */ + continue; + + if (p == 1) { + batch_count++; + /* some unparsed commands remain and batch count less than 20 */ + if (fiber->rbuf->len > 0 && batch_count < 20) + goto dispatch; + } + + r = fiber_flush_output(); + if (r < 0) { + say_debug("flush_output failed, closing connection"); + goto exit; + } + + stats.bytes_written += r; + fiber_gc(); + + if (p == 1 && fiber->rbuf->len > 0) { + batch_count = 0; + goto dispatch; + } + } +exit: + fiber_flush_output(); + fiber_sleep(0.01); + say_debug("exit"); + stats.curr_connections--; /* FIXME: nonlocal exit via exception will leak this counter */ +} + +void +memcached_init(void) +{ + stat_base = stat_register(memcached_stat_strs, memcached_stat_MAX); +} + +void +memcached_expire(void *data __attribute__((unused))) +{ + static khiter_t i; + khash_t(lstr_ptr_map) *map = memcached_index->idx.str_hash; + + say_info("memcached expire fiber started"); + for (;;) { + if (i > kh_end(map)) + i = kh_begin(map); + + struct tbuf *keys_to_delete = tbuf_alloc(fiber->pool); + int expired_keys = 0; + + for (int j = 0; j < cfg.memcached_expire_per_loop; j++, i++) { + if (i == kh_end(map)) { + i = kh_begin(map); + break; + } + + if (!kh_exist(map, i)) + continue; + + struct box_tuple *tuple = kh_value(map, i); + + if (!expired(tuple)) + continue; + + say_debug("expire tuple %p", tuple); + tbuf_append_field(keys_to_delete, tuple->data); + } + + while (keys_to_delete->len > 0) { + struct box_txn *txn = txn_alloc(BOX_QUIET); + @try { + delete(txn, read_field(keys_to_delete)); + expired_keys++; + } + @catch (id e) { + /* The error is already logged. */ + } + } + stat_collect(stat_base, MEMC_EXPIRED_KEYS, expired_keys); + + fiber_gc(); + + double delay = (double)cfg.memcached_expire_per_loop * cfg.memcached_expire_full_sweep / (map->size + 1); + if (delay > 1) + delay = 1; + fiber_sleep(delay); + } +} + +/* + * Local Variables: + * mode: c + * End: + * vim: syntax=objc + */ -- GitLab