From fe6e4d8fa08a7c0c836cbb8a01a1afe1bf625227 Mon Sep 17 00:00:00 2001 From: "Jader H. Silva" Date: Tue, 9 Sep 2014 11:08:39 -0300 Subject: [PATCH] support "touch" command --- src/memc_touch.rl | 17 + src/ngx_http_memc_handler.c | 10 +- src/ngx_http_memc_module.h | 2 + src/ngx_http_memc_request.c | 75 ++++ src/ngx_http_memc_request.h | 1 + src/ngx_http_memc_response.c | 641 +++++++++++++++++++++++++++++----- src/ngx_http_memc_response.rl | 34 ++ src/ngx_http_memc_util.c | 4 + t/touch.t | 85 +++++ 9 files changed, 780 insertions(+), 89 deletions(-) create mode 100644 src/memc_touch.rl create mode 100644 t/touch.t diff --git a/src/memc_touch.rl b/src/memc_touch.rl new file mode 100644 index 0000000..5ad1452 --- /dev/null +++ b/src/memc_touch.rl @@ -0,0 +1,17 @@ +%%{ + machine memc_touch; + + alphtype short; + + include memc_common "memc_common.rl"; + + response = "TOUCHED\r\n" + | "NOT_FOUND\r\n" @handle_not_found + | error + ; + + main := response @finalize + ; + +}%% + diff --git a/src/ngx_http_memc_handler.c b/src/ngx_http_memc_handler.c index 6edd0b6..eb312c8 100644 --- a/src/ngx_http_memc_handler.c +++ b/src/ngx_http_memc_handler.c @@ -281,6 +281,13 @@ ngx_http_memc_handler(ngx_http_request_t *r) u->input_filter_init = ngx_http_memc_empty_filter_init; u->input_filter = ngx_http_memc_empty_filter; + } else if (memc_cmd == ngx_http_memc_cmd_touch) { + u->create_request = ngx_http_memc_create_touch_cmd_request; + u->process_header = ngx_http_memc_process_simple_header; + + u->input_filter_init = ngx_http_memc_empty_filter_init; + u->input_filter = ngx_http_memc_empty_filter; + } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "assertion failed: command \"%v\" does not have proper " @@ -297,7 +304,8 @@ ngx_http_memc_handler(ngx_http_request_t *r) if (is_storage_cmd || memc_cmd == ngx_http_memc_cmd_flush_all - || memc_cmd == ngx_http_memc_cmd_delete) + || memc_cmd == ngx_http_memc_cmd_delete + || memc_cmd == ngx_http_memc_cmd_touch) { exptime_vv = ngx_http_get_indexed_variable(r, mmcf->exptime_index); diff --git a/src/ngx_http_memc_module.h b/src/ngx_http_memc_module.h index bea4578..e622cbf 100644 --- a/src/ngx_http_memc_module.h +++ b/src/ngx_http_memc_module.h @@ -33,6 +33,8 @@ typedef enum { ngx_http_memc_cmd_flush_all, ngx_http_memc_cmd_version, + + ngx_http_memc_cmd_touch, /* ngx_http_memc_cmd_verbosity, */ /* we do not want to support the "quit" command here */ diff --git a/src/ngx_http_memc_request.c b/src/ngx_http_memc_request.c index 1b8e527..23cbe37 100644 --- a/src/ngx_http_memc_request.c +++ b/src/ngx_http_memc_request.c @@ -569,3 +569,78 @@ ngx_http_memc_create_incr_decr_cmd_request(ngx_http_request_t *r) return NGX_OK; } + + +ngx_int_t +ngx_http_memc_create_touch_cmd_request(ngx_http_request_t *r) +{ + size_t len; + ngx_buf_t *b; + ngx_http_memc_ctx_t *ctx; + ngx_chain_t *cl; + uintptr_t escape; + ngx_http_variable_value_t *key_vv; + ngx_http_variable_value_t *exptime_vv; + + ctx = ngx_http_get_module_ctx(r, ngx_http_memc_module); + + /* prepare the "key" argument */ + + key_vv = ctx->memc_key_vv; + + if (key_vv == NULL || key_vv->not_found || key_vv->len == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the \"$memc_key\" variable is not set"); + return NGX_ERROR; + } + + escape = 2 * ngx_escape_uri(NULL, key_vv->data, key_vv->len, + NGX_ESCAPE_MEMCACHED); + + /* prepare the "exptime" argument */ + + exptime_vv = ctx->memc_exptime_vv; + + if (exptime_vv == NULL || exptime_vv->not_found || exptime_vv->len == 0) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "the \"$memc_exptime\" variable is not set"); + return NGX_ERROR; + } + + len = ctx->cmd_str.len + sizeof(' ') + key_vv->len + escape + sizeof(' ') + + exptime_vv->len + sizeof(CRLF) - 1; + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + cl->next = NULL; + + r->upstream->request_bufs = cl; + + b->last = ngx_copy(b->last, ctx->cmd_str.data, ctx->cmd_str.len); + + *b->last++ = ' '; + + if (escape == 0) { + b->last = ngx_copy(b->last, key_vv->data, key_vv->len); + + } else { + b->last = (u_char *) ngx_escape_uri(b->last, key_vv->data, key_vv->len, + NGX_ESCAPE_MEMCACHED); + } + + *b->last++ = ' '; + b->last = ngx_copy(b->last, exptime_vv->data, exptime_vv->len); + + *b->last++ = CR; *b->last++ = LF; + + return NGX_OK; +} diff --git a/src/ngx_http_memc_request.h b/src/ngx_http_memc_request.h index 10e74c6..bdf31c0 100644 --- a/src/ngx_http_memc_request.h +++ b/src/ngx_http_memc_request.h @@ -22,6 +22,7 @@ ngx_int_t ngx_http_memc_create_delete_cmd_request(ngx_http_request_t *r); ngx_int_t ngx_http_memc_create_incr_decr_cmd_request(ngx_http_request_t *r); +ngx_int_t ngx_http_memc_create_touch_cmd_request(ngx_http_request_t *r); #endif /* NGX_HTTP_MEMC_REQUEST_H */ diff --git a/src/ngx_http_memc_response.c b/src/ngx_http_memc_response.c index bcec201..eec83ae 100644 --- a/src/ngx_http_memc_response.c +++ b/src/ngx_http_memc_response.c @@ -101,6 +101,19 @@ static const int memc_incr_decr_en_main = 1; #line 40 "src/ngx_http_memc_response.rl" +#line 42 "src/ngx_http_memc_response.rl" + +#line 107 "src/ngx_http_memc_response.c" +static const int memc_touch_start = 1; +static const int memc_touch_first_final = 45; +static const int memc_touch_error = 0; + +static const int memc_touch_en_main = 1; + + +#line 43 "src/ngx_http_memc_response.rl" + + u_char ngx_http_memc_end[] = CRLF "END" CRLF; @@ -116,6 +129,8 @@ static u_char * parse_memc_delete(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, unsigned *done_addr); static u_char * parse_memc_incr_decr(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, unsigned *done_addr); +static u_char * parse_memc_touch(int *cs_addr, u_char *p, u_char *pe, + ngx_uint_t *status_addr, unsigned *done_addr); static ngx_int_t ngx_http_memc_write_simple_response(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_http_memc_ctx_t *ctx, ngx_uint_t status, ngx_str_t *resp); @@ -150,66 +165,66 @@ ngx_http_memc_process_simple_header(ngx_http_request_t *r) dd("init memc_storage machine..."); -#line 91 "src/ngx_http_memc_response.rl" +#line 96 "src/ngx_http_memc_response.rl" -#line 156 "src/ngx_http_memc_response.c" +#line 171 "src/ngx_http_memc_response.c" { cs = memc_storage_start; } -#line 92 "src/ngx_http_memc_response.rl" +#line 97 "src/ngx_http_memc_response.rl" } else if (ctx->cmd == ngx_http_memc_cmd_flush_all) { dd("init memc_flush_all machine..."); -#line 97 "src/ngx_http_memc_response.rl" +#line 102 "src/ngx_http_memc_response.rl" -#line 169 "src/ngx_http_memc_response.c" +#line 184 "src/ngx_http_memc_response.c" { cs = memc_flush_all_start; } -#line 98 "src/ngx_http_memc_response.rl" +#line 103 "src/ngx_http_memc_response.rl" } else if (ctx->cmd == ngx_http_memc_cmd_version) { dd("init memc_version machine..."); -#line 103 "src/ngx_http_memc_response.rl" +#line 108 "src/ngx_http_memc_response.rl" -#line 182 "src/ngx_http_memc_response.c" +#line 197 "src/ngx_http_memc_response.c" { cs = memc_version_start; } -#line 104 "src/ngx_http_memc_response.rl" +#line 109 "src/ngx_http_memc_response.rl" } else if (ctx->cmd == ngx_http_memc_cmd_stats) { dd("init memc_stats machine..."); -#line 109 "src/ngx_http_memc_response.rl" +#line 114 "src/ngx_http_memc_response.rl" -#line 195 "src/ngx_http_memc_response.c" +#line 210 "src/ngx_http_memc_response.c" { cs = memc_stats_start; } -#line 110 "src/ngx_http_memc_response.rl" +#line 115 "src/ngx_http_memc_response.rl" } else if (ctx->cmd == ngx_http_memc_cmd_delete) { dd("init memc_delete machine..."); -#line 115 "src/ngx_http_memc_response.rl" +#line 120 "src/ngx_http_memc_response.rl" -#line 208 "src/ngx_http_memc_response.c" +#line 223 "src/ngx_http_memc_response.c" { cs = memc_delete_start; } -#line 116 "src/ngx_http_memc_response.rl" +#line 121 "src/ngx_http_memc_response.rl" } else if (ctx->cmd == ngx_http_memc_cmd_incr || ctx->cmd == ngx_http_memc_cmd_decr) @@ -217,14 +232,27 @@ ngx_http_memc_process_simple_header(ngx_http_request_t *r) dd("init memc_incr_decr machine..."); -#line 123 "src/ngx_http_memc_response.rl" +#line 128 "src/ngx_http_memc_response.rl" -#line 223 "src/ngx_http_memc_response.c" +#line 238 "src/ngx_http_memc_response.c" { cs = memc_incr_decr_start; } -#line 124 "src/ngx_http_memc_response.rl" +#line 129 "src/ngx_http_memc_response.rl" + + } else if (ctx->cmd == ngx_http_memc_cmd_touch) { + dd("init memc_touch machine..."); + + +#line 134 "src/ngx_http_memc_response.rl" + +#line 251 "src/ngx_http_memc_response.c" + { + cs = memc_touch_start; + } + +#line 135 "src/ngx_http_memc_response.rl" } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, @@ -292,6 +320,13 @@ ngx_http_memc_process_simple_header(ngx_http_request_t *r) p = (s_char *) parse_memc_incr_decr(&cs, (u_char *) p, (u_char *) pe, &status, &done); + } else if (ctx->cmd == ngx_http_memc_cmd_touch) { + error_state = memc_touch_error; + final_state = memc_touch_first_final; + + p = (s_char *) parse_memc_touch(&cs, (u_char *) p, (u_char *) pe, + &status, &done); + } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unrecognized memcached command in " @@ -678,11 +713,11 @@ parse_memc_storage(int *cs_addr, u_char *p, u_char *pe, int cs = *cs_addr; -#line 577 "src/ngx_http_memc_response.rl" +#line 595 "src/ngx_http_memc_response.rl" -#line 578 "src/ngx_http_memc_response.rl" +#line 596 "src/ngx_http_memc_response.rl" -#line 686 "src/ngx_http_memc_response.c" +#line 721 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -850,7 +885,7 @@ case 15: if ( ++p == pe ) goto _test_eof54; case 54: -#line 854 "src/ngx_http_memc_response.c" +#line 889 "src/ngx_http_memc_response.c" goto st0; st16: if ( ++p == pe ) @@ -1183,7 +1218,7 @@ case 53: _out: {} } -#line 579 "src/ngx_http_memc_response.rl" +#line 597 "src/ngx_http_memc_response.rl" *cs_addr = cs; @@ -1198,11 +1233,11 @@ parse_memc_flush_all(int *cs_addr, u_char *p, u_char *pe, int cs = *cs_addr; -#line 593 "src/ngx_http_memc_response.rl" +#line 611 "src/ngx_http_memc_response.rl" -#line 594 "src/ngx_http_memc_response.rl" +#line 612 "src/ngx_http_memc_response.rl" -#line 1206 "src/ngx_http_memc_response.c" +#line 1241 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -1344,7 +1379,7 @@ case 15: if ( ++p == pe ) goto _test_eof30; case 30: -#line 1348 "src/ngx_http_memc_response.c" +#line 1383 "src/ngx_http_memc_response.c" goto st0; st16: if ( ++p == pe ) @@ -1479,7 +1514,7 @@ case 29: _out: {} } -#line 595 "src/ngx_http_memc_response.rl" +#line 613 "src/ngx_http_memc_response.rl" *cs_addr = cs; @@ -1494,11 +1529,11 @@ parse_memc_version(int *cs_addr, u_char *p, u_char *pe, int cs = *cs_addr; -#line 609 "src/ngx_http_memc_response.rl" +#line 627 "src/ngx_http_memc_response.rl" -#line 610 "src/ngx_http_memc_response.rl" +#line 628 "src/ngx_http_memc_response.rl" -#line 1502 "src/ngx_http_memc_response.c" +#line 1537 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -1633,7 +1668,7 @@ case 15: if ( ++p == pe ) goto _test_eof39; case 39: -#line 1637 "src/ngx_http_memc_response.c" +#line 1672 "src/ngx_http_memc_response.c" goto st0; st16: if ( ++p == pe ) @@ -1795,7 +1830,7 @@ case 36: if ( ++p == pe ) goto _test_eof40; case 40: -#line 1799 "src/ngx_http_memc_response.c" +#line 1834 "src/ngx_http_memc_response.c" if ( (*p) == 13 ) goto st36; goto st35; @@ -1858,7 +1893,7 @@ case 38: _out: {} } -#line 611 "src/ngx_http_memc_response.rl" +#line 629 "src/ngx_http_memc_response.rl" *cs_addr = cs; @@ -1873,11 +1908,11 @@ parse_memc_stats(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, int cs = *cs_addr; -#line 625 "src/ngx_http_memc_response.rl" +#line 643 "src/ngx_http_memc_response.rl" -#line 626 "src/ngx_http_memc_response.rl" +#line 644 "src/ngx_http_memc_response.rl" -#line 1881 "src/ngx_http_memc_response.c" +#line 1916 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -2018,7 +2053,7 @@ case 15: if ( ++p == pe ) goto _test_eof43; case 43: -#line 2022 "src/ngx_http_memc_response.c" +#line 2057 "src/ngx_http_memc_response.c" goto st0; st16: if ( ++p == pe ) @@ -2220,7 +2255,7 @@ case 40: if ( ++p == pe ) goto _test_eof44; case 44: -#line 2224 "src/ngx_http_memc_response.c" +#line 2259 "src/ngx_http_memc_response.c" switch( (*p) ) { case 13: goto st35; case 69: goto st37; @@ -2289,7 +2324,7 @@ case 42: _out: {} } -#line 627 "src/ngx_http_memc_response.rl" +#line 645 "src/ngx_http_memc_response.rl" *cs_addr = cs; @@ -2304,11 +2339,11 @@ parse_memc_delete(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, int cs = *cs_addr; -#line 641 "src/ngx_http_memc_response.rl" +#line 659 "src/ngx_http_memc_response.rl" -#line 642 "src/ngx_http_memc_response.rl" +#line 660 "src/ngx_http_memc_response.rl" -#line 2312 "src/ngx_http_memc_response.c" +#line 2347 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -2464,7 +2499,7 @@ case 15: if ( ++p == pe ) goto _test_eof45; case 45: -#line 2468 "src/ngx_http_memc_response.c" +#line 2503 "src/ngx_http_memc_response.c" goto st0; st16: if ( ++p == pe ) @@ -2719,7 +2754,7 @@ case 44: _out: {} } -#line 643 "src/ngx_http_memc_response.rl" +#line 661 "src/ngx_http_memc_response.rl" *cs_addr = cs; @@ -2734,11 +2769,11 @@ parse_memc_incr_decr(int *cs_addr, u_char *p, u_char *pe, int cs = *cs_addr; -#line 657 "src/ngx_http_memc_response.rl" +#line 675 "src/ngx_http_memc_response.rl" -#line 658 "src/ngx_http_memc_response.rl" +#line 676 "src/ngx_http_memc_response.rl" -#line 2742 "src/ngx_http_memc_response.c" +#line 2777 "src/ngx_http_memc_response.c" { if ( p == pe ) goto _test_eof; @@ -2768,7 +2803,7 @@ cs = 0; if ( ++p == pe ) goto _test_eof2; case 2: -#line 2772 "src/ngx_http_memc_response.c" +#line 2807 "src/ngx_http_memc_response.c" switch( (*p) ) { case 13: goto tr6; case 32: goto tr7; @@ -2787,7 +2822,7 @@ case 2: if ( ++p == pe ) goto _test_eof3; case 3: -#line 2791 "src/ngx_http_memc_response.c" +#line 2826 "src/ngx_http_memc_response.c" if ( (*p) == 10 ) goto tr8; goto st0; @@ -2850,7 +2885,7 @@ case 3: if ( ++p == pe ) goto _test_eof40; case 40: -#line 2854 "src/ngx_http_memc_response.c" +#line 2889 "src/ngx_http_memc_response.c" goto st0; tr7: #line 26 "src/memc_common.rl" @@ -2863,7 +2898,7 @@ case 40: if ( ++p == pe ) goto _test_eof4; case 4: -#line 2867 "src/ngx_http_memc_response.c" +#line 2902 "src/ngx_http_memc_response.c" switch( (*p) ) { case 13: goto tr6; case 32: goto tr7; @@ -2880,7 +2915,7 @@ case 4: if ( ++p == pe ) goto _test_eof5; case 5: -#line 2884 "src/ngx_http_memc_response.c" +#line 2919 "src/ngx_http_memc_response.c" if ( (*p) == 76 ) goto tr9; goto st0; @@ -2895,7 +2930,7 @@ case 5: if ( ++p == pe ) goto _test_eof6; case 6: -#line 2899 "src/ngx_http_memc_response.c" +#line 2934 "src/ngx_http_memc_response.c" if ( (*p) == 73 ) goto tr10; goto st0; @@ -2910,7 +2945,7 @@ case 6: if ( ++p == pe ) goto _test_eof7; case 7: -#line 2914 "src/ngx_http_memc_response.c" +#line 2949 "src/ngx_http_memc_response.c" if ( (*p) == 69 ) goto tr11; goto st0; @@ -2925,7 +2960,7 @@ case 7: if ( ++p == pe ) goto _test_eof8; case 8: -#line 2929 "src/ngx_http_memc_response.c" +#line 2964 "src/ngx_http_memc_response.c" if ( (*p) == 78 ) goto tr12; goto st0; @@ -2940,7 +2975,7 @@ case 8: if ( ++p == pe ) goto _test_eof9; case 9: -#line 2944 "src/ngx_http_memc_response.c" +#line 2979 "src/ngx_http_memc_response.c" if ( (*p) == 84 ) goto tr13; goto st0; @@ -2955,7 +2990,7 @@ case 9: if ( ++p == pe ) goto _test_eof10; case 10: -#line 2959 "src/ngx_http_memc_response.c" +#line 2994 "src/ngx_http_memc_response.c" if ( (*p) == 95 ) goto tr14; goto st0; @@ -2970,7 +3005,7 @@ case 10: if ( ++p == pe ) goto _test_eof11; case 11: -#line 2974 "src/ngx_http_memc_response.c" +#line 3009 "src/ngx_http_memc_response.c" if ( (*p) == 69 ) goto tr15; goto st0; @@ -2985,7 +3020,7 @@ case 11: if ( ++p == pe ) goto _test_eof12; case 12: -#line 2989 "src/ngx_http_memc_response.c" +#line 3024 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr16; goto st0; @@ -3000,7 +3035,7 @@ case 12: if ( ++p == pe ) goto _test_eof13; case 13: -#line 3004 "src/ngx_http_memc_response.c" +#line 3039 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr17; goto st0; @@ -3015,7 +3050,7 @@ case 13: if ( ++p == pe ) goto _test_eof14; case 14: -#line 3019 "src/ngx_http_memc_response.c" +#line 3054 "src/ngx_http_memc_response.c" if ( (*p) == 79 ) goto tr18; goto st0; @@ -3030,7 +3065,7 @@ case 14: if ( ++p == pe ) goto _test_eof15; case 15: -#line 3034 "src/ngx_http_memc_response.c" +#line 3069 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr19; goto st0; @@ -3045,7 +3080,7 @@ case 15: if ( ++p == pe ) goto _test_eof16; case 16: -#line 3049 "src/ngx_http_memc_response.c" +#line 3084 "src/ngx_http_memc_response.c" if ( (*p) == 32 ) goto tr20; goto st0; @@ -3060,7 +3095,7 @@ case 16: if ( ++p == pe ) goto _test_eof17; case 17: -#line 3064 "src/ngx_http_memc_response.c" +#line 3099 "src/ngx_http_memc_response.c" if ( (*p) == 13 ) goto tr21; goto tr20; @@ -3075,7 +3110,7 @@ case 17: if ( ++p == pe ) goto _test_eof18; case 18: -#line 3079 "src/ngx_http_memc_response.c" +#line 3114 "src/ngx_http_memc_response.c" switch( (*p) ) { case 10: goto tr22; case 13: goto tr21; @@ -3092,7 +3127,7 @@ case 18: if ( ++p == pe ) goto _test_eof19; case 19: -#line 3096 "src/ngx_http_memc_response.c" +#line 3131 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr23; goto st0; @@ -3107,7 +3142,7 @@ case 19: if ( ++p == pe ) goto _test_eof20; case 20: -#line 3111 "src/ngx_http_memc_response.c" +#line 3146 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr24; goto st0; @@ -3122,7 +3157,7 @@ case 20: if ( ++p == pe ) goto _test_eof21; case 21: -#line 3126 "src/ngx_http_memc_response.c" +#line 3161 "src/ngx_http_memc_response.c" if ( (*p) == 79 ) goto tr25; goto st0; @@ -3137,7 +3172,7 @@ case 21: if ( ++p == pe ) goto _test_eof22; case 22: -#line 3141 "src/ngx_http_memc_response.c" +#line 3176 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr26; goto st0; @@ -3152,7 +3187,7 @@ case 22: if ( ++p == pe ) goto _test_eof23; case 23: -#line 3156 "src/ngx_http_memc_response.c" +#line 3191 "src/ngx_http_memc_response.c" if ( (*p) == 13 ) goto tr27; goto st0; @@ -3167,7 +3202,7 @@ case 23: if ( ++p == pe ) goto _test_eof24; case 24: -#line 3171 "src/ngx_http_memc_response.c" +#line 3206 "src/ngx_http_memc_response.c" if ( (*p) == 10 ) goto tr22; goto st0; @@ -3182,7 +3217,7 @@ case 24: if ( ++p == pe ) goto _test_eof25; case 25: -#line 3186 "src/ngx_http_memc_response.c" +#line 3221 "src/ngx_http_memc_response.c" if ( (*p) == 79 ) goto tr28; goto st0; @@ -3197,7 +3232,7 @@ case 25: if ( ++p == pe ) goto _test_eof26; case 26: -#line 3201 "src/ngx_http_memc_response.c" +#line 3236 "src/ngx_http_memc_response.c" if ( (*p) == 84 ) goto tr29; goto st0; @@ -3212,7 +3247,7 @@ case 26: if ( ++p == pe ) goto _test_eof27; case 27: -#line 3216 "src/ngx_http_memc_response.c" +#line 3251 "src/ngx_http_memc_response.c" if ( (*p) == 95 ) goto tr30; goto st0; @@ -3227,7 +3262,7 @@ case 27: if ( ++p == pe ) goto _test_eof28; case 28: -#line 3231 "src/ngx_http_memc_response.c" +#line 3266 "src/ngx_http_memc_response.c" if ( (*p) == 70 ) goto tr31; goto st0; @@ -3242,7 +3277,7 @@ case 28: if ( ++p == pe ) goto _test_eof29; case 29: -#line 3246 "src/ngx_http_memc_response.c" +#line 3281 "src/ngx_http_memc_response.c" if ( (*p) == 79 ) goto tr32; goto st0; @@ -3257,7 +3292,7 @@ case 29: if ( ++p == pe ) goto _test_eof30; case 30: -#line 3261 "src/ngx_http_memc_response.c" +#line 3296 "src/ngx_http_memc_response.c" if ( (*p) == 85 ) goto tr33; goto st0; @@ -3272,7 +3307,7 @@ case 30: if ( ++p == pe ) goto _test_eof31; case 31: -#line 3276 "src/ngx_http_memc_response.c" +#line 3311 "src/ngx_http_memc_response.c" if ( (*p) == 78 ) goto tr34; goto st0; @@ -3287,7 +3322,7 @@ case 31: if ( ++p == pe ) goto _test_eof32; case 32: -#line 3291 "src/ngx_http_memc_response.c" +#line 3326 "src/ngx_http_memc_response.c" if ( (*p) == 68 ) goto tr35; goto st0; @@ -3302,7 +3337,7 @@ case 32: if ( ++p == pe ) goto _test_eof33; case 33: -#line 3306 "src/ngx_http_memc_response.c" +#line 3341 "src/ngx_http_memc_response.c" if ( (*p) == 13 ) goto tr36; goto st0; @@ -3317,7 +3352,7 @@ case 33: if ( ++p == pe ) goto _test_eof34; case 34: -#line 3321 "src/ngx_http_memc_response.c" +#line 3356 "src/ngx_http_memc_response.c" if ( (*p) == 10 ) goto tr37; goto st0; @@ -3332,7 +3367,7 @@ case 34: if ( ++p == pe ) goto _test_eof35; case 35: -#line 3336 "src/ngx_http_memc_response.c" +#line 3371 "src/ngx_http_memc_response.c" if ( (*p) == 69 ) goto tr38; goto st0; @@ -3347,7 +3382,7 @@ case 35: if ( ++p == pe ) goto _test_eof36; case 36: -#line 3351 "src/ngx_http_memc_response.c" +#line 3386 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr39; goto st0; @@ -3362,7 +3397,7 @@ case 36: if ( ++p == pe ) goto _test_eof37; case 37: -#line 3366 "src/ngx_http_memc_response.c" +#line 3401 "src/ngx_http_memc_response.c" if ( (*p) == 86 ) goto tr40; goto st0; @@ -3377,7 +3412,7 @@ case 37: if ( ++p == pe ) goto _test_eof38; case 38: -#line 3381 "src/ngx_http_memc_response.c" +#line 3416 "src/ngx_http_memc_response.c" if ( (*p) == 69 ) goto tr41; goto st0; @@ -3392,7 +3427,7 @@ case 38: if ( ++p == pe ) goto _test_eof39; case 39: -#line 3396 "src/ngx_http_memc_response.c" +#line 3431 "src/ngx_http_memc_response.c" if ( (*p) == 82 ) goto tr13; goto st0; @@ -3441,7 +3476,437 @@ case 39: _out: {} } -#line 659 "src/ngx_http_memc_response.rl" +#line 677 "src/ngx_http_memc_response.rl" + + *cs_addr = cs; + + return p; +} + + +static u_char * +parse_memc_touch(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, + unsigned *done_addr) +{ + int cs = *cs_addr; + + +#line 691 "src/ngx_http_memc_response.rl" + +#line 692 "src/ngx_http_memc_response.rl" + +#line 3499 "src/ngx_http_memc_response.c" + { + if ( p == pe ) + goto _test_eof; + switch ( cs ) + { +case 1: + switch( (*p) ) { + case 67: goto st2; + case 69: goto st16; + case 78: goto st22; + case 83: goto st32; + case 84: goto st37; + } + goto st0; +st0: +cs = 0; + goto _out; +st2: + if ( ++p == pe ) + goto _test_eof2; +case 2: + if ( (*p) == 76 ) + goto st3; + goto st0; +st3: + if ( ++p == pe ) + goto _test_eof3; +case 3: + if ( (*p) == 73 ) + goto st4; + goto st0; +st4: + if ( ++p == pe ) + goto _test_eof4; +case 4: + if ( (*p) == 69 ) + goto st5; + goto st0; +st5: + if ( ++p == pe ) + goto _test_eof5; +case 5: + if ( (*p) == 78 ) + goto st6; + goto st0; +st6: + if ( ++p == pe ) + goto _test_eof6; +case 6: + if ( (*p) == 84 ) + goto st7; + goto st0; +st7: + if ( ++p == pe ) + goto _test_eof7; +case 7: + if ( (*p) == 95 ) + goto st8; + goto st0; +st8: + if ( ++p == pe ) + goto _test_eof8; +case 8: + if ( (*p) == 69 ) + goto st9; + goto st0; +st9: + if ( ++p == pe ) + goto _test_eof9; +case 9: + if ( (*p) == 82 ) + goto st10; + goto st0; +st10: + if ( ++p == pe ) + goto _test_eof10; +case 10: + if ( (*p) == 82 ) + goto st11; + goto st0; +st11: + if ( ++p == pe ) + goto _test_eof11; +case 11: + if ( (*p) == 79 ) + goto st12; + goto st0; +st12: + if ( ++p == pe ) + goto _test_eof12; +case 12: + if ( (*p) == 82 ) + goto st13; + goto st0; +st13: + if ( ++p == pe ) + goto _test_eof13; +case 13: + if ( (*p) == 32 ) + goto st14; + goto st0; +st14: + if ( ++p == pe ) + goto _test_eof14; +case 14: + if ( (*p) == 13 ) + goto st15; + goto st14; +st15: + if ( ++p == pe ) + goto _test_eof15; +case 15: + switch( (*p) ) { + case 10: goto tr19; + case 13: goto st15; + } + goto st14; +tr19: +#line 4 "src/memc_common.rl" + { + dd("caught error..."); + dd("machine state: %d", cs); + + *status_addr = NGX_HTTP_BAD_GATEWAY; + } +#line 21 "src/memc_common.rl" + { + dd("done it!"); + *done_addr = 1; + } + goto st45; +tr34: +#line 37 "src/memc_common.rl" + { + dd("status set to 404"); + + *status_addr = NGX_HTTP_NOT_FOUND; + } +#line 21 "src/memc_common.rl" + { + dd("done it!"); + *done_addr = 1; + } + goto st45; +tr46: +#line 21 "src/memc_common.rl" + { + dd("done it!"); + *done_addr = 1; + } + goto st45; +st45: + if ( ++p == pe ) + goto _test_eof45; +case 45: +#line 3655 "src/ngx_http_memc_response.c" + goto st0; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: + if ( (*p) == 82 ) + goto st17; + goto st0; +st17: + if ( ++p == pe ) + goto _test_eof17; +case 17: + if ( (*p) == 82 ) + goto st18; + goto st0; +st18: + if ( ++p == pe ) + goto _test_eof18; +case 18: + if ( (*p) == 79 ) + goto st19; + goto st0; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: + if ( (*p) == 82 ) + goto st20; + goto st0; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + if ( (*p) == 13 ) + goto st21; + goto st0; +st21: + if ( ++p == pe ) + goto _test_eof21; +case 21: + if ( (*p) == 10 ) + goto tr19; + goto st0; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: + if ( (*p) == 79 ) + goto st23; + goto st0; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: + if ( (*p) == 84 ) + goto st24; + goto st0; +st24: + if ( ++p == pe ) + goto _test_eof24; +case 24: + if ( (*p) == 95 ) + goto st25; + goto st0; +st25: + if ( ++p == pe ) + goto _test_eof25; +case 25: + if ( (*p) == 70 ) + goto st26; + goto st0; +st26: + if ( ++p == pe ) + goto _test_eof26; +case 26: + if ( (*p) == 79 ) + goto st27; + goto st0; +st27: + if ( ++p == pe ) + goto _test_eof27; +case 27: + if ( (*p) == 85 ) + goto st28; + goto st0; +st28: + if ( ++p == pe ) + goto _test_eof28; +case 28: + if ( (*p) == 78 ) + goto st29; + goto st0; +st29: + if ( ++p == pe ) + goto _test_eof29; +case 29: + if ( (*p) == 68 ) + goto st30; + goto st0; +st30: + if ( ++p == pe ) + goto _test_eof30; +case 30: + if ( (*p) == 13 ) + goto st31; + goto st0; +st31: + if ( ++p == pe ) + goto _test_eof31; +case 31: + if ( (*p) == 10 ) + goto tr34; + goto st0; +st32: + if ( ++p == pe ) + goto _test_eof32; +case 32: + if ( (*p) == 69 ) + goto st33; + goto st0; +st33: + if ( ++p == pe ) + goto _test_eof33; +case 33: + if ( (*p) == 82 ) + goto st34; + goto st0; +st34: + if ( ++p == pe ) + goto _test_eof34; +case 34: + if ( (*p) == 86 ) + goto st35; + goto st0; +st35: + if ( ++p == pe ) + goto _test_eof35; +case 35: + if ( (*p) == 69 ) + goto st36; + goto st0; +st36: + if ( ++p == pe ) + goto _test_eof36; +case 36: + if ( (*p) == 82 ) + goto st7; + goto st0; +st37: + if ( ++p == pe ) + goto _test_eof37; +case 37: + if ( (*p) == 79 ) + goto st38; + goto st0; +st38: + if ( ++p == pe ) + goto _test_eof38; +case 38: + if ( (*p) == 85 ) + goto st39; + goto st0; +st39: + if ( ++p == pe ) + goto _test_eof39; +case 39: + if ( (*p) == 67 ) + goto st40; + goto st0; +st40: + if ( ++p == pe ) + goto _test_eof40; +case 40: + if ( (*p) == 72 ) + goto st41; + goto st0; +st41: + if ( ++p == pe ) + goto _test_eof41; +case 41: + if ( (*p) == 69 ) + goto st42; + goto st0; +st42: + if ( ++p == pe ) + goto _test_eof42; +case 42: + if ( (*p) == 68 ) + goto st43; + goto st0; +st43: + if ( ++p == pe ) + goto _test_eof43; +case 43: + if ( (*p) == 13 ) + goto st44; + goto st0; +st44: + if ( ++p == pe ) + goto _test_eof44; +case 44: + if ( (*p) == 10 ) + goto tr46; + goto st0; + } + _test_eof2: cs = 2; goto _test_eof; + _test_eof3: cs = 3; goto _test_eof; + _test_eof4: cs = 4; goto _test_eof; + _test_eof5: cs = 5; goto _test_eof; + _test_eof6: cs = 6; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof45: cs = 45; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + _test_eof29: cs = 29; goto _test_eof; + _test_eof30: cs = 30; goto _test_eof; + _test_eof31: cs = 31; goto _test_eof; + _test_eof32: cs = 32; goto _test_eof; + _test_eof33: cs = 33; goto _test_eof; + _test_eof34: cs = 34; goto _test_eof; + _test_eof35: cs = 35; goto _test_eof; + _test_eof36: cs = 36; goto _test_eof; + _test_eof37: cs = 37; goto _test_eof; + _test_eof38: cs = 38; goto _test_eof; + _test_eof39: cs = 39; goto _test_eof; + _test_eof40: cs = 40; goto _test_eof; + _test_eof41: cs = 41; goto _test_eof; + _test_eof42: cs = 42; goto _test_eof; + _test_eof43: cs = 43; goto _test_eof; + _test_eof44: cs = 44; goto _test_eof; + + _test_eof: {} + _out: {} + } + +#line 693 "src/ngx_http_memc_response.rl" *cs_addr = cs; diff --git a/src/ngx_http_memc_response.rl b/src/ngx_http_memc_response.rl index 1be10be..29ba6ac 100644 --- a/src/ngx_http_memc_response.rl +++ b/src/ngx_http_memc_response.rl @@ -38,6 +38,9 @@ %% machine memc_incr_decr; %% write data; +%% machine memc_touch; +%% write data; + u_char ngx_http_memc_end[] = CRLF "END" CRLF; @@ -54,6 +57,8 @@ static u_char * parse_memc_delete(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, unsigned *done_addr); static u_char * parse_memc_incr_decr(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, unsigned *done_addr); +static u_char * parse_memc_touch(int *cs_addr, u_char *p, u_char *pe, + ngx_uint_t *status_addr, unsigned *done_addr); static ngx_int_t ngx_http_memc_write_simple_response(ngx_http_request_t *r, ngx_http_upstream_t *u, ngx_http_memc_ctx_t *ctx, ngx_uint_t status, ngx_str_t *resp); @@ -122,6 +127,12 @@ ngx_http_memc_process_simple_header(ngx_http_request_t *r) %% machine memc_incr_decr; %% write init; + } else if (ctx->cmd == ngx_http_memc_cmd_touch) { + dd("init memc_touch machine..."); + + %% machine memc_touch; + %% write init; + } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unrecognized memcached command in " @@ -188,6 +199,13 @@ ngx_http_memc_process_simple_header(ngx_http_request_t *r) p = (s_char *) parse_memc_incr_decr(&cs, (u_char *) p, (u_char *) pe, &status, &done); + } else if (ctx->cmd == ngx_http_memc_cmd_touch) { + error_state = memc_touch_error; + final_state = memc_touch_first_final; + + p = (s_char *) parse_memc_touch(&cs, (u_char *) p, (u_char *) pe, + &status, &done); + } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "unrecognized memcached command in " @@ -661,3 +679,19 @@ parse_memc_incr_decr(int *cs_addr, u_char *p, u_char *pe, return p; } + + +static u_char * +parse_memc_touch(int *cs_addr, u_char *p, u_char *pe, ngx_uint_t *status_addr, + unsigned *done_addr) +{ + int cs = *cs_addr; + + %% machine memc_touch; + %% include "memc_touch.rl"; + %% write exec; + + *cs_addr = cs; + + return p; +} diff --git a/src/ngx_http_memc_util.c b/src/ngx_http_memc_util.c index 090bf43..9984927 100644 --- a/src/ngx_http_memc_util.c +++ b/src/ngx_http_memc_util.c @@ -61,6 +61,10 @@ ngx_http_memc_parse_cmd(u_char *data, size_t len, ngx_flag_t *is_storage_cmd) return ngx_http_memc_cmd_stats; } + if (ngx_http_memc_strcmp_const(data, "touch") == 0) { + return ngx_http_memc_cmd_touch; + } + break; case 6: diff --git a/t/touch.t b/t/touch.t new file mode 100644 index 0000000..6fa5756 --- /dev/null +++ b/t/touch.t @@ -0,0 +1,85 @@ +# vi:filetype= + +use lib 'lib'; +use Test::Nginx::Socket; + +plan tests => repeat_each() * 2 * blocks(); + +$ENV{TEST_NGINX_MEMCACHED_PORT} ||= 11211; + +#no_diff; + +run_tests(); + +__DATA__ + +=== TEST 1: touch non-existent item +--- config + location /main { + echo 'flush_all'; + echo_location '/memc?cmd=flush_all'; + + echo 'touch foo'; + echo_location '/memc?key=foo&cmd=touch&exptime=1'; + + echo_blocking_sleep 1.6; + } + location /memc { + echo_before_body "status: $echo_response_status"; + echo_before_body "exptime: $memc_exptime"; + + set $memc_cmd $arg_cmd; + set $memc_key $arg_key; + set $memc_value $arg_val; + set $memc_exptime $arg_exptime; + + memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT; + } +--- request + GET /main +--- response_body_like +^flush_all +status: 200 +exptime: +OK\r +touch foo +status: 404 +exptime: 1 +.*?404 Not Found.*$ + + + +=== TEST 2: set and touch +--- config + location /main { + echo 'set foo bar'; + echo_location '/memc?cmd=set&key=foo&val=bar'; + + echo 'touch foo 1'; + echo_location '/memc?key=foo&cmd=touch&exptime=1'; + } + location /memc { + echo_before_body "status: $echo_response_status"; + echo_before_body "exptime: $memc_exptime"; + + set $memc_cmd $arg_cmd; + set $memc_key $arg_key; + set $memc_value $arg_val; + set $memc_exptime $arg_exptime; + + memc_pass 127.0.0.1:$TEST_NGINX_MEMCACHED_PORT; + } +--- request + GET /main +--- response_body eval +"set foo bar +status: 201 +exptime: 0 +STORED\r +delete foo 1 +status: 200 +exptime: 1 +TOUCHED\r +" +--- SKIP +