Skip to content

Commit 950244b

Browse files
committed
meta: minor protocol adjustments
remove EN\r\n trailer from valid mg responses. VA is the status code, EN is redundant. quiet mode elides the EN on miss. meta-noop now has a dedicated MN status code for clarity. fix bug in return data for "mg key\r\n" updates tests for new changes. also updates documentation.
1 parent 04613a4 commit 950244b

File tree

3 files changed

+122
-110
lines changed

3 files changed

+122
-110
lines changed

doc/protocol.txt

Lines changed: 72 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -96,24 +96,30 @@ noted in the 'Commands' section above.
9696

9797
All meta commands follow a basic syntax:
9898

99-
cm <key> <flags> <token1> <token2> <...>\r\n
99+
<cm> <key> <flag1> <flag2> <...>\r\n
100100

101-
Where 'cm' is a 2 character command code. The number of tokens supplied is
102-
based off of the flags used.
101+
Where <cm> is a 2 character command code.
103102

104103
Responses look like:
105104

106-
RC <flags> <token1> <token2> <...>\r\n
105+
<RC> <flag1> <flag2> <...>\r\n
107106

108-
Where 'rc' is a 2 character return code. The number of tokens returned are
109-
based off of the flags used.
107+
Where <RC> is a 2 character return code. The number of flags returned are
108+
based off of the flags supplied.
110109

111110
Flags are single character codes, ie 'q' or 'k' or 'I', which adjust the
112111
behavior of the command. The flags are reflected in the response. The order of
113112
which tokens are consumed or returned depend on the order of the flags given.
114113
For example, a metaget with flags of 'st' would return tokens for "size" and
115114
"TTL remaining" in that order. 'ts' would return "TTL remaining" then "size".
116115

116+
Flags are single character codes, ie 'q' or 'k' or 'O', which adjust the
117+
behavior of a command. Flags may contain token arguments, which come after the
118+
flag and before the next space or newline, ie 'Oopaque' or 'Kuserkey'. Flags
119+
can return new data or reflect information, in the same order they were
120+
supplied in the request. Sending an 't' flag with a get for an item with 20
121+
seconds of TTL remaining, would return 't20' in the response.
122+
117123
Syntax errors are handled the same as noted under 'Error strings' section
118124
below.
119125

@@ -456,7 +462,11 @@ me <key>\r\n
456462

457463
The response looks like:
458464

459-
ME <key> <k>=<v>*\r\nEN\r\n
465+
ME <key> <k>=<v>*\r\n
466+
467+
A miss looks like:
468+
469+
EN\r\n
460470

461471
Each of the keys and values are the internal data for the item.
462472

@@ -476,22 +486,15 @@ The meta get command is the generic command for retrieving key data from
476486
memcached. Based on the flags supplied, it can replace all of the commands:
477487
"get", "gets", "gat", "gats", "touch", as well as adding new options.
478488

479-
mg <key> <flags> <tokens>*\r\n
489+
mg <key> <flags>*\r\n
480490

481491
- <key> means one key string. Unlike "get" metaget can only take a single key.
482492

483493
- <flags> are a set of single character codes ended with a space or newline.
484-
485-
- <tokens>* means zero or more tokens, based on the flags supplied. They are
486-
consumed in order specified by the flags.
494+
flags may have strings after the initial character.
487495

488496
After this command, the client expects an item to be returned, received as a
489-
text line followed by an optional data block. After the item is transferred,
490-
the server sends the string
491-
492-
"EN\r\n"
493-
494-
to indicate the end of the response.
497+
text line followed by an optional data block.
495498

496499
If a response line appearing in a retrieval request is not sent back
497500
by the server this means that the server does not
@@ -501,36 +504,46 @@ deleted by a client).
501504

502505
An item sent by the server looks like:
503506

504-
VA <flags> <tokens>*\r\n
507+
VA <size> <flags>*\r\n
505508
<data block>\r\n
506509

507-
- <flags> are a reflection of the flags sent to the server. Extra flags can be
508-
added to the response based on the execution of the command.
510+
- <size> is the size of <data block> in bytes, minus the \r\n
509511

510-
- <tokens>* are tokens returned by the server, based on the flags supplied.
512+
- <flags>* are tokens returned by the server, based on the flags supplied.
511513
They are added in order specified by the flags sent.
512514

513515
- <data block> is the data for this item. Note that the data black is
514516
optional, requiring the 'v' flag to be supplied.
515517

518+
If the request did not ask for a value in the response (v) flag, the server
519+
response instead looks like:
520+
521+
HD <flags>*\r\n
522+
523+
If the request resulted in a miss, the response looks like:
524+
525+
EN\r\n
526+
527+
Unless the (q) flag was supplied, which suppresses the status code for a miss.
528+
516529
The flags used by the 'mg' command are:
517530

518531
- c: return item cas token
519532
- f: return client flags token
520533
- h: return whether item has been hit before as a 0 or 1
521534
- k: return key as a token
522535
- l: return time since item was last accessed in seconds
523-
- O (token): opaque value, consumes a token and copies back with response
536+
- O(token): opaque value, consumes a token and copies back with response
524537
- q: use noreply semantics for return codes.
525538
- s: return item size token
526539
- t: return item TTL remaining in seconds (-1 for unlimited)
527540
- u: don't bump the item in the LRU
528541
- v: return item value in <data block>
529542

530543
These flags can modify the item:
531-
- N (token): vivify on miss, takes TTL as a argument
532-
- R (token): if token is less than remaining TTL win for recache
533-
- T (token): update remaining TTL
544+
- N(token): vivify on miss, takes TTL as a argument
545+
- R(token): if token is less than remaining TTL win for recache
546+
- T(token): update remaining TTL
534547

535548
These extra flags can be added to the response:
536549
- W: client has "won" the recache flag
@@ -546,9 +559,9 @@ The above two flags return the value of "hit before?" and "last access time"
546559
before the command was processed. Otherwise this would always show a 1 for
547560
hit or always show an access time of "0" unless combined with the "u" flag.
548561

549-
- O (token): opaque value, consumes a token and copies back with response
562+
- O(token): opaque value, consumes a token and copies back with response
550563

551-
The O (opaque) token is used by this and other commands to allow easier
564+
The O(opaque) token is used by this and other commands to allow easier
552565
pipelining of requests while saving bytes on the wire for responses. For
553566
example: if pipelining three get commands together, you may not know which
554567
response belongs to which without also retrieving the key. If the key is very
@@ -581,10 +594,10 @@ access time.
581594
- v: return item value in <data block>
582595

583596
The data block for a metaget response is optional, requiring this flag to be
584-
passed in.
597+
passed in. The response code also changes from "HD" to "VA <size>"
585598

586599
These flags can modify the item:
587-
- N (token): vivify on miss, takes TTL as a argument
600+
- N(token): vivify on miss, takes TTL as a argument
588601

589602
Used to help with so called "dog piling" problems with recaching of popular
590603
items. If supplied, and metaget does not find the item in cache, it will
@@ -599,14 +612,14 @@ already received the win flag.
599612

600613
Can be combined with CAS flags to gate the update further.
601614

602-
- R (token): if token is less than remaining TTL win for recache
615+
- R(token): if token is less than remaining TTL win for recache
603616

604617
Similar to and can be combined with 'N'. If the remaining TTL of an item is
605618
below the supplied token, return a 'W' flag to indicate the client has "won"
606619
the right to recache an item. This allows refreshing an item before it leads to
607620
a miss.
608621

609-
- T (token): update remaining TTL
622+
- T(token): update remaining TTL
610623

611624
Similar to "touch" and "gat" commands, updates the remaining TTL of an item if
612625
hit.
@@ -646,27 +659,25 @@ The meta set command a generic command for storing data to memcached. Based on
646659
the flags supplied, it can replace the commands: "set", "cas". as well as
647660
adding new options.
648661

649-
ms <key> <flags> <tokens>*\r\n
662+
ms <key> <flags>*\r\n
650663

651664
- <key> means one key string.
652665

653666
- <flags> are a set of single character codes ended with a space or newline.
654-
655-
- <tokens>* means zero or more tokens, based on the flags supplied. They are
656-
consumed in order specified by the flags.
667+
flags may have strings after the initial character.
657668

658669
After this line, the client sends the data block:
659670

660671
<data block>\r\n
661672

662673
- <data block> is a chunk of arbitrary 8-bit data of length supplied by an 'S'
663-
flag and token from the previous line. If no 'S' flag is supplied the data
674+
flag and token from the request line. If no 'S' flag is supplied the data
664675
is assumed to be 0 length.
665676

666677
After sending the command line and the data block the client awaits
667678
the reply, which is of the format:
668679

669-
CD <flags> <tokens>*\r\n
680+
<CD> <flags> <tokens>*\r\n
670681

671682
Where CD is one of:
672683

@@ -683,33 +694,33 @@ with CAS semantics did not exist.
683694

684695
The flags used by the 'ms' command are:
685696

686-
- C (token): compare CAS value when storing item
687-
- F (token): set client flags to token (32 bit unsigned numeric)
688-
- I: invalid. set-to-invalid if CAS is older than it should be.
697+
- C(token): compare CAS value when storing item
698+
- F(token): set client flags to token (32 bit unsigned numeric)
699+
- I: invalidate. set-to-invalid if supplied CAS is older than item's CAS
689700
- k: return key as a token
690-
- O (token): opaque value, consumes a token and copies back with response
701+
- O(token): opaque value, consumes a token and copies back with response
691702
- q: use noreply semantics for return codes
692-
- S (token): size of <data block> to store
693-
- T (token): Time-To-Live for item, see "Expiration" above.
703+
- S(token): size of <data block> to store
704+
- T(token): Time-To-Live for item, see "Expiration" above.
694705

695706
The flags are now repeated with detailed information where useful:
696707

697-
- C (token): compare CAS value when storing item
708+
- C(token): compare CAS value when storing item
698709

699710
Similar to the basic "cas" command, only store item if the supplied token
700711
matches the current CAS value of the item. When combined with the 'I' flag, a
701712
CAS value that is _lower_ than the current value may be accepted, but the item
702713
will be marked as "stale", returning the X flag with mget requests.
703714

704-
- F (token): set client flags to token (32 bit unsigned numeric)
715+
- F(token): set client flags to token (32 bit unsigned numeric)
705716

706717
Sets flags to 0 if not supplied.
707718

708719
- I: invalid. set-to-invalid if CAS is older than it should be.
709720

710721
Functional when combined with 'C' flag above.
711722

712-
- O (token): opaque value, consumes a token and copies back with response
723+
- O(token): opaque value, consumes a token and copies back with response
713724

714725
See description under 'Meta Get'
715726

@@ -728,18 +739,16 @@ Meta Delete
728739
The meta delete command allows for explicit deletion of items, as well as
729740
marking items as "stale" to allow serving items as stale during revalidation.
730741

731-
md <key> <flags> <tokens>*\r\n
742+
md <key> <flags>*\r\n
732743

733744
- <key> means one key string.
734745

735746
- <flags> are a set of single character codes ended with a space or newline.
736-
737-
- <tokens>* means zero or more tokens, based on the flags supplied. They are
738-
consumed in order specified by the flags.
747+
flags may have strings after the initial character.
739748

740749
The response is in the format:
741750

742-
CD <flags> <tokens>*\r\n
751+
<CD> <flags> <tokens>*\r\n
743752

744753
Where CD is one of:
745754

@@ -752,16 +761,16 @@ Where CD is one of:
752761

753762
The flags used by the 'md' command are:
754763

755-
- C (token): compare CAS value
764+
- C(token): compare CAS value
756765
- I: invalidate. mark as stale, bumps CAS.
757766
- k: return key
758-
- O: opaque to copy back.
767+
- O(token): opaque to copy back.
759768
- q: noreply
760-
- T (token): updates TTL, only when paired with the 'I' flag
769+
- T(token): updates TTL, only when paired with the 'I' flag
761770

762771
The flags are now repeated with detailed information where useful:
763772

764-
- C (token): compare CAS value
773+
- C(token): compare CAS value
765774

766775
Can be used to only delete or mark-stale if a supplied CAS value matches.
767776

@@ -771,7 +780,7 @@ Instead of removing an item, this will give the item a new CAS value and mark
771780
it as stale. This means when it is later fetched by metaget, the client will
772781
be supplied an 'X' flag to show the data is stale and needs to be recached.
773782

774-
- O (token): opaque to copy back.
783+
- O(token): opaque to copy back.
775784

776785
See description under 'Meta Get'
777786

@@ -780,7 +789,7 @@ See description under 'Meta Get'
780789
See description under 'Meta Set'. In the case of meta delete, this will hide
781790
response lines with the code "DE". It will still return any other responses.
782791

783-
- T (token): updates TTL, only when paired with the 'I' flag
792+
- T(token): updates TTL, only when paired with the 'I' flag
784793

785794
When marking an item as stale with 'I', the 'T' flag can be used to update the
786795
TTL as well; limiting the amount of time an item will live while stale and
@@ -794,16 +803,14 @@ takes no flags, no arguments.
794803

795804
This returns the static response:
796805

797-
"EN\r\n"
798-
799-
Similar to a meta get command.
806+
"MN\r\n"
800807

801808
This command is useful when used with the 'q' flag and pipelining commands.
802-
For example, with 'mg' the response lines are blank on miss, and the 'q' flag
803-
will hide the "EN\r\n" response code. If pipelining several 'mg's together
804-
with noreply semantics, an "mn\r\n" command can be tagged to the end of the
805-
chain, which will return an "EN\r\n", signalling to a client that all previous
806-
commands have been processed.
809+
For example, with 'mg' the response lines are blank on miss when the 'q' flag
810+
is supplied. If pipelining several 'mg's together with noreply semantics, an
811+
"mn\r\n" command can be tagged to the end of the chain, which will return an
812+
"MN\r\n", signalling to a client that all previous commands have been
813+
processed.
807814

808815
Slabs Reassign
809816
--------------

memcached.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3663,12 +3663,24 @@ static void _get_extstore_cb(void *e, obj_io *io, int ret) {
36633663
resp->chunked_data_iov = 0;
36643664
} else {
36653665
int i;
3666-
// Wipe the iovecs up through our data injection.
3667-
// Allows trailers to be returned (EN)
3668-
for (i = 0; i <= wrap->iovec_data; i++) {
3669-
resp->tosend -= resp->iov[i].iov_len;
3670-
resp->iov[i].iov_len = 0;
3671-
resp->iov[i].iov_base = NULL;
3666+
// Meta commands have EN status lines for miss, rather than
3667+
// END as a trailer as per normal ascii.
3668+
if (resp->iov[0].iov_len >= 3
3669+
&& memcmp(resp->iov[0].iov_base, "VA ", 3) == 0) {
3670+
// TODO: These miss translators should use specific callback
3671+
// functions attached to the io wrap. This is weird :(
3672+
resp->iovcnt = 1;
3673+
resp->iov[0].iov_len = 4;
3674+
resp->iov[0].iov_base = "EN\r\n";
3675+
resp->tosend = 4;
3676+
} else {
3677+
// Wipe the iovecs up through our data injection.
3678+
// Allows trailers to be returned (END)
3679+
for (i = 0; i <= wrap->iovec_data; i++) {
3680+
resp->tosend -= resp->iov[i].iov_len;
3681+
resp->iov[i].iov_len = 0;
3682+
resp->iov[i].iov_base = NULL;
3683+
}
36723684
}
36733685
resp->chunked_total = 0;
36743686
resp->chunked_data_iov = 0;
@@ -4032,7 +4044,7 @@ static void process_meta_command(conn *c, token_t *tokens, const size_t ntokens)
40324044
total++;
40334045

40344046
ret = snprintf(resp->wbuf + total, WRITE_BUFFER_SIZE - (it->nkey + 12),
4035-
"exp=%d la=%llu cas=%llu fetch=%s cls=%u size=%lu\r\nEN\r\n",
4047+
"exp=%d la=%llu cas=%llu fetch=%s cls=%u size=%lu\r\n",
40364048
(it->exptime == 0) ? -1 : (current_time - it->exptime),
40374049
(unsigned long long)(current_time - it->time),
40384050
(unsigned long long)ITEM_get_cas(it),
@@ -4171,6 +4183,7 @@ static void process_mget_command(conn *c, token_t *tokens, const size_t ntokens)
41714183
if (ntokens == 3) {
41724184
// TODO: any way to fix this?
41734185
out_errstring(c, "CLIENT_ERROR bad command line format");
4186+
return;
41744187
} else if (ntokens > MFLAG_MAX_OPT_LENGTH) {
41754188
// TODO: ensure the command tokenizer gives us at least this many
41764189
out_errstring(c, "CLIENT_ERROR options flags are too long");
@@ -4378,10 +4391,6 @@ static void process_mget_command(conn *c, token_t *tokens, const size_t ntokens)
43784391
#endif
43794392
}
43804393

4381-
if (!c->noreply) {
4382-
resp_add_iov(resp, "EN\r\n", 4);
4383-
}
4384-
43854394
// need to hold the ref at least because of the key above.
43864395
#ifdef EXTSTORE
43874396
if (!failed) {
@@ -5458,7 +5467,7 @@ static void process_command(conn *c, char *command) {
54585467
} else if (ntokens >= 3 && (strcmp(tokens[COMMAND_TOKEN].value, "md") == 0)) {
54595468
process_mdelete_command(c, tokens, ntokens);
54605469
} else if (ntokens >= 2 && (strcmp(tokens[COMMAND_TOKEN].value, "mn") == 0)) {
5461-
out_string(c, "EN");
5470+
out_string(c, "MN");
54625471
// mn command forces immediate writeback flush.
54635472
conn_set_state(c, conn_mwrite);
54645473
return;

0 commit comments

Comments
 (0)