diff options
author | dormando <dormando@rydia.net> | 2022-03-01 12:51:47 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2022-03-01 12:51:47 -0800 |
commit | fa745db8fffe7d13438fe2437bdf8fcb1372bc96 (patch) | |
tree | 15bd7946d2d9ac6631c635f5c7ac12228e078f0b /proxy_request.c | |
parent | 2a903f04d1b395cd60c1b7357a9b733e19eb7973 (diff) | |
download | memcached-fa745db8fffe7d13438fe2437bdf8fcb1372bc96.tar.gz |
proxy: hacky method of supporting noreply/quiet
avoids sending the response to the client, in most cases. works by
stripping the noreply status from the request before sending it along,
so the proxy itself knows when to move the request forward.
has sharp edges:
- only looking at the request object that's actually sent to the
backend, instead of the request object that created the coroutine.
- overriding tokens in lua to re-set the noreply mode would break the
protocol.
So this change helps us validate the feature but solidifying it requires
moving it to the "edges" of processing; before the coroutine and after
any command assembly (or within the command assembly).
Diffstat (limited to 'proxy_request.c')
-rw-r--r-- | proxy_request.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/proxy_request.c b/proxy_request.c index c52f9d9..9aecf5b 100644 --- a/proxy_request.c +++ b/proxy_request.c @@ -43,6 +43,9 @@ static int _process_tokenize(mcp_parser_t *pr, const size_t max) { } endloop: + // endcap token so we can quickly find the length of any token by looking + // at the next one. + pr->tokens[curtoken] = len; pr->ntokens = curtoken; P_DEBUG("%s: cur_tokens: %d\n", __func__, curtoken); @@ -124,7 +127,7 @@ static int _process_request_metaflags(mcp_parser_t *pr, int token) { return -1; } P_DEBUG("%s: setting meta flag: %d\n", __func__, *cur - 65); - pr->t.meta.flags |= 1 << (*cur - 65); + pr->t.meta.flags |= (uint64_t)1 << (*cur - 65); state = 1; } break; @@ -138,6 +141,13 @@ static int _process_request_metaflags(mcp_parser_t *pr, int token) { } } + // not too great hack for noreply detection: this can be flattened out + // once a few other contexts are fixed and we detect the noreply from the + // coroutine start instead. + if (pr->t.meta.flags & ((uint64_t)1 << 48)) { + pr->noreply = true; + } + return 0; } @@ -198,6 +208,18 @@ static int _process_request_gat(mcp_parser_t *pr) { return 0; } +#define NOREPLYSTR "noreply" +#define NOREPLYLEN sizeof(NOREPLYSTR)-1 +// given a tokenized parser for a normal ASCII command, checks for noreply +// mode. +static int _process_request_noreply(mcp_parser_t *pr) { + if (pr->tokens[pr->ntokens] - pr->tokens[pr->ntokens-1] >= NOREPLYLEN + && strncmp(NOREPLYSTR, pr->request + pr->tokens[pr->ntokens-1], NOREPLYLEN) == 0) { + pr->noreply = true; + } + return 0; +} + // we need t find the bytes supplied immediately so we can read the request // from the client properly. // set <key> <flags> <exptime> <bytes> [noreply]\r\n @@ -226,7 +248,7 @@ static int _process_request_storage(mcp_parser_t *pr, size_t max) { pr->vlen = vlen; - return 0; + return _process_request_noreply(pr); } // common request with key: <cmd> <key> <args> @@ -235,7 +257,7 @@ static int _process_request_simple(mcp_parser_t *pr, const size_t max) { pr->keytoken = 1; // second token is usually the key... stupid GAT. _process_request_key(pr); - return 0; + return _process_request_noreply(pr); } // TODO: return code ENUM with error types. @@ -278,6 +300,7 @@ int process_request(mcp_parser_t *pr, const char *command, size_t cmdlen) { break; case 2: if (cm[0] == 'm') { + type = CMD_TYPE_META; switch (cm[1]) { case 'g': cmd = CMD_MG; |