From b2688ebbf53ba837d9cfc1078fc444cfba1b7e5b Mon Sep 17 00:00:00 2001
From: Roman Tokarev <rtokarev@corp.mail.ru>
Date: Tue, 26 Apr 2011 13:51:49 +0400
Subject: [PATCH] A fix for Bug#769040

A fix for
http://bugs.launchpad.net/bugs/769040
"Incomplete error output in Memcached protocol"

Append an error description to a memcached error answer.
---
 core/iproto.c              |   1 +
 include/iproto.h           |  59 ++--
 include/util.h             |   7 +-
 mod/silverbox/memcached.c  | 564 +++++++++++++++++++------------------
 mod/silverbox/memcached.rl |  40 ++-
 5 files changed, 353 insertions(+), 318 deletions(-)

diff --git a/core/iproto.c b/core/iproto.c
index 820a8aa412..83519646f8 100644
--- a/core/iproto.c
+++ b/core/iproto.c
@@ -35,6 +35,7 @@
 
 const uint32_t msg_ping = 0xff00;
 STRS(error_codes, ERROR_CODES);
+DESC_STRS(error_codes, ERROR_CODES);
 
 static struct tbuf *
 iproto_parse(struct tbuf *in)
diff --git a/include/iproto.h b/include/iproto.h
index 9ad3d5d124..4256e2c767 100644
--- a/include/iproto.h
+++ b/include/iproto.h
@@ -38,39 +38,40 @@ struct iproto_interactor
 
 void iproto_interact(void *);
 
-#define ERROR_CODES(_)							\
-	_(ERR_CODE_OK,                    0x00000000) /* OK */		\
-	_(ERR_CODE_NONMASTER,             0x00000102) /* Non master connection, but it should be */ \
-	_(ERR_CODE_ILLEGAL_PARAMS,        0x00000202) /* Illegal parametrs */ \
-	_(ERR_CODE_BAD_UID,               0x00000302) /* Uid not from this storage range */ \
-	_(ERR_CODE_NODE_IS_RO,            0x00000401) /* Node is marked as read-only */ \
-	_(ERR_CODE_NODE_IS_NOT_LOCKED,    0x00000501) /* Node isn't locked */ \
-	_(ERR_CODE_NODE_IS_LOCKED,        0x00000601) /* Node is locked */ \
-	_(ERR_CODE_MEMORY_ISSUE,          0x00000701) /* Some memory issues */ \
-	_(ERR_CODE_BAD_INTEGRITY,         0x00000802) /* Bad graph integrity */ \
-	_(ERR_CODE_UNSUPPORTED_COMMAND,   0x00000a02) /* Unsupported command */ \
+#define ERROR_CODES(_)					    \
+	_(ERR_CODE_OK,                    0x00000000, "ok") \
+	_(ERR_CODE_NONMASTER,             0x00000102, "non master connection, but it should be") \
+	_(ERR_CODE_ILLEGAL_PARAMS,        0x00000202, "illegal parametrs") \
+	_(ERR_CODE_BAD_UID,               0x00000302, "uid not from this storage range") \
+	_(ERR_CODE_NODE_IS_RO,            0x00000401, "node is marked as read-only") \
+	_(ERR_CODE_NODE_IS_NOT_LOCKED,    0x00000501, "node isn't locked") \
+	_(ERR_CODE_NODE_IS_LOCKED,        0x00000601, "node is locked") \
+	_(ERR_CODE_MEMORY_ISSUE,          0x00000701, "some memory issues") \
+	_(ERR_CODE_BAD_INTEGRITY,         0x00000802, "bad graph integrity") \
+	_(ERR_CODE_UNSUPPORTED_COMMAND,   0x00000a02, "unsupported command") \
 	/* gap due to silverproxy */					\
-	_(ERR_CODE_CANNOT_REGISTER,       0x00001801) /* Can't register new user */ \
-	_(ERR_CODE_CANNOT_INIT_ALERT_ID,  0x00001a01) /* Can't generate alert id */ \
-	_(ERR_CODE_CANNOT_DEL,            0x00001b02) /* Can't del node */ \
-	_(ERR_CODE_USER_NOT_REGISTERED,   0x00001c02) /* User isn't registered */ \
+	_(ERR_CODE_CANNOT_REGISTER,       0x00001801, "can't register new user") \
+	_(ERR_CODE_CANNOT_INIT_ALERT_ID,  0x00001a01, "can't generate alert id") \
+	_(ERR_CODE_CANNOT_DEL,            0x00001b02, "can't del node") \
+	_(ERR_CODE_USER_NOT_REGISTERED,   0x00001c02, "user isn't registered") \
 	/* silversearch error codes */					\
-	_(ERR_CODE_SYNTAX_ERROR,          0x00001d02) /* Syntax error in query */ \
-	_(ERR_CODE_WRONG_FIELD,           0x00001e02) /* Unknown field */ \
-	_(ERR_CODE_WRONG_NUMBER,          0x00001f02) /* Number value is out of range */ \
-	_(ERR_CODE_DUPLICATE,             0x00002002) /* Insert already existing object */ \
-	_(ERR_CODE_UNSUPPORTED_ORDER,     0x00002202) /* Can not order result */ \
-	_(ERR_CODE_MULTIWRITE,            0x00002302) /* Multiple to update/delete */ \
-	_(ERR_CODE_NOTHING,               0x00002400) /* nothing to do (not an error) */ \
-	_(ERR_CODE_UPDATE_ID,             0x00002502) /* id's update */ \
-	_(ERR_CODE_WRONG_VERSION,         0x00002602)	/* unsupported version of protocol */ \
+	_(ERR_CODE_SYNTAX_ERROR,          0x00001d02, "syntax error in query") \
+	_(ERR_CODE_WRONG_FIELD,           0x00001e02, "unknown field") \
+	_(ERR_CODE_WRONG_NUMBER,          0x00001f02, "number value is out of range") \
+	_(ERR_CODE_DUPLICATE,             0x00002002, "insert already existing object") \
+	_(ERR_CODE_UNSUPPORTED_ORDER,     0x00002202, "can not order result") \
+	_(ERR_CODE_MULTIWRITE,            0x00002302, "multiple to update/delete") \
+	_(ERR_CODE_NOTHING,               0x00002400, "nothing to do (not an error)") \
+	_(ERR_CODE_UPDATE_ID,             0x00002502, "id's update") \
+	_(ERR_CODE_WRONG_VERSION,         0x00002602, "unsupported version of protocol") \
 	/* other generic error codes */					\
-	_(ERR_CODE_UNKNOWN_ERROR,         0x00002702) \
-        _(ERR_CODE_NODE_NOT_FOUND,	  0x00003102) \
-	_(ERR_CODE_NODE_FOUND,		  0x00003702) \
-	_(ERR_CODE_INDEX_VIOLATION,	  0x00003802) \
-	_(ERR_CODE_NO_SUCH_NAMESPACE,	  0x00003902)
+	_(ERR_CODE_UNKNOWN_ERROR,         0x00002702, "unknown error") \
+        _(ERR_CODE_NODE_NOT_FOUND,	  0x00003102, "node isn't found") \
+	_(ERR_CODE_NODE_FOUND,		  0x00003702, "node is found") \
+	_(ERR_CODE_INDEX_VIOLATION,	  0x00003802, "some index violation occur") \
+	_(ERR_CODE_NO_SUCH_NAMESPACE,	  0x00003902, "there is no such namespace")
 
 ENUM(error_codes, ERROR_CODES);
 extern char *error_codes_strs[];
+extern char *error_codes_desc_strs[];
 #endif
diff --git a/include/util.h b/include/util.h
index dc3ccbd9ca..21236285b8 100644
--- a/include/util.h
+++ b/include/util.h
@@ -35,11 +35,14 @@
 #endif
 
 /* Macros to define enum and corresponding strings. */
-#define ENUM_MEMBER(s, v) s = v,
-#define ENUM_STRS_MEMBER(s, v) [s] = #s,
+#define ENUM_MEMBER(s, v, d...) s = v,
+#define ENUM_STRS_MEMBER(s, v, d...) [s] = #s,
+#define ENUM_DESC_STRS_MEMBER(s, v, d...) [s] = d,
 #define ENUM(enum_name, enum_members) enum enum_name {enum_members(ENUM_MEMBER) enum_name##_MAX}
 #define STRS(enum_name, enum_members) \
 	char *enum_name##_strs[enum_name##_MAX + 1] = {enum_members(ENUM_STRS_MEMBER) '\0'}
+#define DESC_STRS(enum_name, enum_members) \
+	char *enum_name##_desc_strs[enum_name##_MAX + 1] = {enum_members(ENUM_DESC_STRS_MEMBER) '\0'}
 
 // Macros for printf functions
 #include <inttypes.h>
diff --git a/mod/silverbox/memcached.c b/mod/silverbox/memcached.c
index c6100fdc38..6a8006e463 100644
--- a/mod/silverbox/memcached.c
+++ b/mod/silverbox/memcached.c
@@ -32,6 +32,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 
+#include <iproto.h>
 #include <salloc.h>
 #include <palloc.h>
 #include <fiber.h>
@@ -66,7 +67,7 @@ struct meta {
 } __packed__;
 
 
-#line 70 "mod/silverbox/memcached.c"
+#line 71 "mod/silverbox/memcached.c"
 static const int memcached_start = 1;
 static const int memcached_first_final = 197;
 static const int memcached_error = 0;
@@ -74,7 +75,7 @@ static const int memcached_error = 0;
 static const int memcached_en_main = 1;
 
 
-#line 69 "mod/silverbox/memcached.rl"
+#line 70 "mod/silverbox/memcached.rl"
 
 
 
@@ -248,27 +249,31 @@ memcached_dispatch(struct box_txn *txn)
 
 	say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p);
 
-#define STORE ({							\
-	stats.cmd_set++;						\
-	if (bytes > (1<<20)) {						\
-		add_iov("SERVER_ERROR object too large for cache\r\n", 41); \
-	} else {							\
-		if (store(txn, key, exptime, flags, bytes, data) == 0) { \
-			stats.total_items++;				\
-			add_iov("STORED\r\n", 8);			\
-		} else {						\
-			add_iov("SERVER_ERROR\r\n", 14);		\
-		}							\
-	}								\
+#define STORE ({									\
+	stats.cmd_set++;								\
+	if (bytes > (1<<20)) {								\
+		add_iov("SERVER_ERROR object too large for cache\r\n", 41);		\
+	} else {									\
+		u32 ret_code;								\
+		if ((ret_code = store(txn, key, exptime, flags, bytes, data)) == 0) {	\
+			stats.total_items++;						\
+			add_iov("STORED\r\n", 8);					\
+		} else {								\
+			add_iov("SERVER_ERROR ", 13);					\
+			add_iov(error_codes_desc_strs[ret_code],			\
+				strlen(error_codes_desc_strs[ret_code]));		\
+			add_iov("\r\n", 2);						\
+		}									\
+	}										\
 })
 
 	
-#line 267 "mod/silverbox/memcached.c"
+#line 272 "mod/silverbox/memcached.c"
 	{
 	cs = memcached_start;
 	}
 
-#line 272 "mod/silverbox/memcached.c"
+#line 277 "mod/silverbox/memcached.c"
 	{
 	if ( p == pe )
 		goto _test_eof;
@@ -326,7 +331,7 @@ case 5:
 		goto st0;
 	goto tr15;
 tr15:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -343,7 +348,7 @@ case 5:
 	if ( ++p == pe )
 		goto _test_eof6;
 case 6:
-#line 347 "mod/silverbox/memcached.c"
+#line 352 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st7;
 	goto st0;
@@ -357,49 +362,49 @@ case 7:
 		goto tr17;
 	goto st0;
 tr17:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st8;
 st8:
 	if ( ++p == pe )
 		goto _test_eof8;
 case 8:
-#line 368 "mod/silverbox/memcached.c"
+#line 373 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr18;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st8;
 	goto st0;
 tr18:
-#line 501 "mod/silverbox/memcached.rl"
+#line 511 "mod/silverbox/memcached.rl"
 	{flags = natoq(fstart, p);}
 	goto st9;
 st9:
 	if ( ++p == pe )
 		goto _test_eof9;
 case 9:
-#line 382 "mod/silverbox/memcached.c"
+#line 387 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st9;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr21;
 	goto st0;
 tr21:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st10;
 st10:
 	if ( ++p == pe )
 		goto _test_eof10;
 case 10:
-#line 396 "mod/silverbox/memcached.c"
+#line 401 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr22;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st10;
 	goto st0;
 tr22:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -410,21 +415,21 @@ case 10:
 	if ( ++p == pe )
 		goto _test_eof11;
 case 11:
-#line 414 "mod/silverbox/memcached.c"
+#line 419 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st11;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr25;
 	goto st0;
 tr25:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st12;
 st12:
 	if ( ++p == pe )
 		goto _test_eof12;
 case 12:
-#line 428 "mod/silverbox/memcached.c"
+#line 433 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr26;
 		case 13: goto tr27;
@@ -434,11 +439,11 @@ case 12:
 		goto st12;
 	goto st0;
 tr26:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -459,13 +464,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 262 "mod/silverbox/memcached.rl"
+#line 267 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -476,9 +481,9 @@ case 12:
 		}
 	goto st197;
 tr30:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -499,13 +504,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 262 "mod/silverbox/memcached.rl"
+#line 267 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -516,11 +521,11 @@ case 12:
 		}
 	goto st197;
 tr39:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -541,13 +546,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 262 "mod/silverbox/memcached.rl"
+#line 267 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -558,11 +563,11 @@ case 12:
 		}
 	goto st197;
 tr58:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -583,13 +588,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 291 "mod/silverbox/memcached.rl"
+#line 296 "mod/silverbox/memcached.rl"
 	{
 			struct tbuf *b;
 			void *value;
@@ -618,9 +623,9 @@ case 12:
 		}
 	goto st197;
 tr62:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -641,13 +646,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 291 "mod/silverbox/memcached.rl"
+#line 296 "mod/silverbox/memcached.rl"
 	{
 			struct tbuf *b;
 			void *value;
@@ -676,11 +681,11 @@ case 12:
 		}
 	goto st197;
 tr71:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -701,13 +706,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 291 "mod/silverbox/memcached.rl"
+#line 296 "mod/silverbox/memcached.rl"
 	{
 			struct tbuf *b;
 			void *value;
@@ -736,11 +741,11 @@ case 12:
 		}
 	goto st197;
 tr91:
-#line 503 "mod/silverbox/memcached.rl"
+#line 513 "mod/silverbox/memcached.rl"
 	{cas = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -761,13 +766,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 280 "mod/silverbox/memcached.rl"
+#line 285 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -780,9 +785,9 @@ case 12:
 		}
 	goto st197;
 tr95:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -803,13 +808,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 280 "mod/silverbox/memcached.rl"
+#line 285 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -822,11 +827,11 @@ case 12:
 		}
 	goto st197;
 tr105:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -847,13 +852,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 280 "mod/silverbox/memcached.rl"
+#line 285 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -866,17 +871,17 @@ case 12:
 		}
 	goto st197;
 tr118:
-#line 504 "mod/silverbox/memcached.rl"
+#line 514 "mod/silverbox/memcached.rl"
 	{incr = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 318 "mod/silverbox/memcached.rl"
+#line 323 "mod/silverbox/memcached.rl"
 	{
 			struct meta *m;
 			struct tbuf *b;
@@ -929,15 +934,15 @@ case 12:
 		}
 	goto st197;
 tr122:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 318 "mod/silverbox/memcached.rl"
+#line 323 "mod/silverbox/memcached.rl"
 	{
 			struct meta *m;
 			struct tbuf *b;
@@ -990,17 +995,17 @@ case 12:
 		}
 	goto st197;
 tr132:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 318 "mod/silverbox/memcached.rl"
+#line 323 "mod/silverbox/memcached.rl"
 	{
 			struct meta *m;
 			struct tbuf *b;
@@ -1053,92 +1058,107 @@ case 12:
 		}
 	goto st197;
 tr141:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 369 "mod/silverbox/memcached.rl"
+#line 374 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
 			if (tuple == NULL || tuple->flags & GHOST || expired(tuple)) {
 				add_iov("NOT_FOUND\r\n", 11);
 			} else {
-				if (delete(txn, key) == 0)
+				u32 ret_code;
+				if ((ret_code = delete(txn, key)) == 0)
 					add_iov("DELETED\r\n", 9);
-				else
-					add_iov("SERVER_ERROR\r\n", 14);
+				else {
+					add_iov("SERVER_ERROR ", 13);
+					add_iov(error_codes_desc_strs[ret_code],
+						strlen(error_codes_desc_strs[ret_code]));
+					add_iov("\r\n", 2);
+				}
 			}
 		}
 	goto st197;
 tr146:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
 				exptime = exptime + ev_now();
 		}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 369 "mod/silverbox/memcached.rl"
+#line 374 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
 			if (tuple == NULL || tuple->flags & GHOST || expired(tuple)) {
 				add_iov("NOT_FOUND\r\n", 11);
 			} else {
-				if (delete(txn, key) == 0)
+				u32 ret_code;
+				if ((ret_code = delete(txn, key)) == 0)
 					add_iov("DELETED\r\n", 9);
-				else
-					add_iov("SERVER_ERROR\r\n", 14);
+				else {
+					add_iov("SERVER_ERROR ", 13);
+					add_iov(error_codes_desc_strs[ret_code],
+						strlen(error_codes_desc_strs[ret_code]));
+					add_iov("\r\n", 2);
+				}
 			}
 		}
 	goto st197;
 tr157:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 369 "mod/silverbox/memcached.rl"
+#line 374 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
 			if (tuple == NULL || tuple->flags & GHOST || expired(tuple)) {
 				add_iov("NOT_FOUND\r\n", 11);
 			} else {
-				if (delete(txn, key) == 0)
+				u32 ret_code;
+				if ((ret_code = delete(txn, key)) == 0)
 					add_iov("DELETED\r\n", 9);
-				else
-					add_iov("SERVER_ERROR\r\n", 14);
+				else {
+					add_iov("SERVER_ERROR ", 13);
+					add_iov(error_codes_desc_strs[ret_code],
+						strlen(error_codes_desc_strs[ret_code]));
+					add_iov("\r\n", 2);
+				}
 			}
 		}
 	goto st197;
 tr169:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 459 "mod/silverbox/memcached.rl"
+#line 469 "mod/silverbox/memcached.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -1150,17 +1170,17 @@ case 12:
 		}
 	goto st197;
 tr174:
-#line 505 "mod/silverbox/memcached.rl"
+#line 515 "mod/silverbox/memcached.rl"
 	{flush_delay = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 459 "mod/silverbox/memcached.rl"
+#line 469 "mod/silverbox/memcached.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -1172,17 +1192,17 @@ case 12:
 		}
 	goto st197;
 tr185:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 459 "mod/silverbox/memcached.rl"
+#line 469 "mod/silverbox/memcached.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -1194,15 +1214,15 @@ case 12:
 		}
 	goto st197;
 tr195:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 382 "mod/silverbox/memcached.rl"
+#line 392 "mod/silverbox/memcached.rl"
 	{
 			txn->op = SELECT;
 			fiber_register_cleanup((void *)txn_cleanup, txn);
@@ -1281,25 +1301,25 @@ case 12:
 		}
 	goto st197;
 tr213:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 473 "mod/silverbox/memcached.rl"
+#line 483 "mod/silverbox/memcached.rl"
 	{
 			return 0;
 		}
 	goto st197;
 tr233:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1320,13 +1340,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 271 "mod/silverbox/memcached.rl"
+#line 276 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -1337,9 +1357,9 @@ case 12:
 		}
 	goto st197;
 tr237:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1360,13 +1380,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 271 "mod/silverbox/memcached.rl"
+#line 276 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -1377,11 +1397,11 @@ case 12:
 		}
 	goto st197;
 tr246:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1402,13 +1422,13 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 271 "mod/silverbox/memcached.rl"
+#line 276 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			struct box_tuple *tuple = find(key);
@@ -1419,11 +1439,11 @@ case 12:
 		}
 	goto st197;
 tr263:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1444,22 +1464,22 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 257 "mod/silverbox/memcached.rl"
+#line 262 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			STORE;
 		}
 	goto st197;
 tr267:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1480,24 +1500,24 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 257 "mod/silverbox/memcached.rl"
+#line 262 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			STORE;
 		}
 	goto st197;
 tr276:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 507 "mod/silverbox/memcached.rl"
+#line 517 "mod/silverbox/memcached.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1518,28 +1538,28 @@ case 12:
 				goto exit;
 			}
 		}
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 257 "mod/silverbox/memcached.rl"
+#line 262 "mod/silverbox/memcached.rl"
 	{
 			key = read_field(keys);
 			STORE;
 		}
 	goto st197;
 tr281:
-#line 534 "mod/silverbox/memcached.rl"
+#line 544 "mod/silverbox/memcached.rl"
 	{ p++; }
-#line 528 "mod/silverbox/memcached.rl"
+#line 538 "mod/silverbox/memcached.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 469 "mod/silverbox/memcached.rl"
+#line 479 "mod/silverbox/memcached.rl"
 	{
 			print_stats();
 		}
@@ -1548,33 +1568,33 @@ case 12:
 	if ( ++p == pe )
 		goto _test_eof197;
 case 197:
-#line 1552 "mod/silverbox/memcached.c"
+#line 1572 "mod/silverbox/memcached.c"
 	goto st0;
 tr27:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st13;
 tr40:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st13;
 st13:
 	if ( ++p == pe )
 		goto _test_eof13;
 case 13:
-#line 1566 "mod/silverbox/memcached.c"
+#line 1586 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr30;
 	goto st0;
 tr28:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st14;
 st14:
 	if ( ++p == pe )
 		goto _test_eof14;
 case 14:
-#line 1578 "mod/silverbox/memcached.c"
+#line 1598 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 32: goto st14;
 		case 110: goto st15;
@@ -1667,18 +1687,18 @@ case 26:
 		goto tr45;
 	goto st0;
 tr45:
-#line 542 "mod/silverbox/memcached.rl"
+#line 552 "mod/silverbox/memcached.rl"
 	{append = true; }
 	goto st27;
 tr209:
-#line 543 "mod/silverbox/memcached.rl"
+#line 553 "mod/silverbox/memcached.rl"
 	{append = false;}
 	goto st27;
 st27:
 	if ( ++p == pe )
 		goto _test_eof27;
 case 27:
-#line 1682 "mod/silverbox/memcached.c"
+#line 1702 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st27;
@@ -1687,7 +1707,7 @@ case 27:
 		goto st0;
 	goto tr46;
 tr46:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1704,7 +1724,7 @@ case 27:
 	if ( ++p == pe )
 		goto _test_eof28;
 case 28:
-#line 1708 "mod/silverbox/memcached.c"
+#line 1728 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st29;
 	goto st0;
@@ -1718,49 +1738,49 @@ case 29:
 		goto tr49;
 	goto st0;
 tr49:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st30;
 st30:
 	if ( ++p == pe )
 		goto _test_eof30;
 case 30:
-#line 1729 "mod/silverbox/memcached.c"
+#line 1749 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr50;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st30;
 	goto st0;
 tr50:
-#line 501 "mod/silverbox/memcached.rl"
+#line 511 "mod/silverbox/memcached.rl"
 	{flags = natoq(fstart, p);}
 	goto st31;
 st31:
 	if ( ++p == pe )
 		goto _test_eof31;
 case 31:
-#line 1743 "mod/silverbox/memcached.c"
+#line 1763 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st31;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr53;
 	goto st0;
 tr53:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st32;
 st32:
 	if ( ++p == pe )
 		goto _test_eof32;
 case 32:
-#line 1757 "mod/silverbox/memcached.c"
+#line 1777 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr54;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st32;
 	goto st0;
 tr54:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1771,21 +1791,21 @@ case 32:
 	if ( ++p == pe )
 		goto _test_eof33;
 case 33:
-#line 1775 "mod/silverbox/memcached.c"
+#line 1795 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st33;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr57;
 	goto st0;
 tr57:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st34;
 st34:
 	if ( ++p == pe )
 		goto _test_eof34;
 case 34:
-#line 1789 "mod/silverbox/memcached.c"
+#line 1809 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr58;
 		case 13: goto tr59;
@@ -1795,30 +1815,30 @@ case 34:
 		goto st34;
 	goto st0;
 tr59:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st35;
 tr72:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st35;
 st35:
 	if ( ++p == pe )
 		goto _test_eof35;
 case 35:
-#line 1810 "mod/silverbox/memcached.c"
+#line 1830 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr62;
 	goto st0;
 tr60:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st36;
 st36:
 	if ( ++p == pe )
 		goto _test_eof36;
 case 36:
-#line 1822 "mod/silverbox/memcached.c"
+#line 1842 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 32: goto st36;
 		case 110: goto st37;
@@ -1908,7 +1928,7 @@ case 47:
 		goto st0;
 	goto tr76;
 tr76:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1925,7 +1945,7 @@ case 47:
 	if ( ++p == pe )
 		goto _test_eof48;
 case 48:
-#line 1929 "mod/silverbox/memcached.c"
+#line 1949 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st49;
 	goto st0;
@@ -1939,49 +1959,49 @@ case 49:
 		goto tr78;
 	goto st0;
 tr78:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st50;
 st50:
 	if ( ++p == pe )
 		goto _test_eof50;
 case 50:
-#line 1950 "mod/silverbox/memcached.c"
+#line 1970 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr79;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st50;
 	goto st0;
 tr79:
-#line 501 "mod/silverbox/memcached.rl"
+#line 511 "mod/silverbox/memcached.rl"
 	{flags = natoq(fstart, p);}
 	goto st51;
 st51:
 	if ( ++p == pe )
 		goto _test_eof51;
 case 51:
-#line 1964 "mod/silverbox/memcached.c"
+#line 1984 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st51;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr82;
 	goto st0;
 tr82:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st52;
 st52:
 	if ( ++p == pe )
 		goto _test_eof52;
 case 52:
-#line 1978 "mod/silverbox/memcached.c"
+#line 1998 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr83;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st52;
 	goto st0;
 tr83:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1992,49 +2012,49 @@ case 52:
 	if ( ++p == pe )
 		goto _test_eof53;
 case 53:
-#line 1996 "mod/silverbox/memcached.c"
+#line 2016 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st53;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr86;
 	goto st0;
 tr86:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st54;
 st54:
 	if ( ++p == pe )
 		goto _test_eof54;
 case 54:
-#line 2010 "mod/silverbox/memcached.c"
+#line 2030 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr87;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st54;
 	goto st0;
 tr87:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st55;
 st55:
 	if ( ++p == pe )
 		goto _test_eof55;
 case 55:
-#line 2024 "mod/silverbox/memcached.c"
+#line 2044 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st55;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr90;
 	goto st0;
 tr90:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st56;
 st56:
 	if ( ++p == pe )
 		goto _test_eof56;
 case 56:
-#line 2038 "mod/silverbox/memcached.c"
+#line 2058 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr91;
 		case 13: goto tr92;
@@ -2044,30 +2064,30 @@ case 56:
 		goto st56;
 	goto st0;
 tr106:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st57;
 tr92:
-#line 503 "mod/silverbox/memcached.rl"
+#line 513 "mod/silverbox/memcached.rl"
 	{cas = natoq(fstart, p);}
 	goto st57;
 st57:
 	if ( ++p == pe )
 		goto _test_eof57;
 case 57:
-#line 2059 "mod/silverbox/memcached.c"
+#line 2079 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr95;
 	goto st0;
 tr93:
-#line 503 "mod/silverbox/memcached.rl"
+#line 513 "mod/silverbox/memcached.rl"
 	{cas = natoq(fstart, p);}
 	goto st58;
 st58:
 	if ( ++p == pe )
 		goto _test_eof58;
 case 58:
-#line 2071 "mod/silverbox/memcached.c"
+#line 2091 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -2128,14 +2148,14 @@ case 65:
 	}
 	goto st0;
 tr107:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st66;
 st66:
 	if ( ++p == pe )
 		goto _test_eof66;
 case 66:
-#line 2139 "mod/silverbox/memcached.c"
+#line 2159 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -2173,18 +2193,18 @@ case 70:
 		goto tr113;
 	goto st0;
 tr113:
-#line 551 "mod/silverbox/memcached.rl"
+#line 561 "mod/silverbox/memcached.rl"
 	{incr_sign = -1;}
 	goto st71;
 tr202:
-#line 550 "mod/silverbox/memcached.rl"
+#line 560 "mod/silverbox/memcached.rl"
 	{incr_sign = 1; }
 	goto st71;
 st71:
 	if ( ++p == pe )
 		goto _test_eof71;
 case 71:
-#line 2188 "mod/silverbox/memcached.c"
+#line 2208 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st71;
@@ -2193,7 +2213,7 @@ case 71:
 		goto st0;
 	goto tr114;
 tr114:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2210,7 +2230,7 @@ case 71:
 	if ( ++p == pe )
 		goto _test_eof72;
 case 72:
-#line 2214 "mod/silverbox/memcached.c"
+#line 2234 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st73;
 	goto st0;
@@ -2224,14 +2244,14 @@ case 73:
 		goto tr117;
 	goto st0;
 tr117:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st74;
 st74:
 	if ( ++p == pe )
 		goto _test_eof74;
 case 74:
-#line 2235 "mod/silverbox/memcached.c"
+#line 2255 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr118;
 		case 13: goto tr119;
@@ -2241,30 +2261,30 @@ case 74:
 		goto st74;
 	goto st0;
 tr133:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st75;
 tr119:
-#line 504 "mod/silverbox/memcached.rl"
+#line 514 "mod/silverbox/memcached.rl"
 	{incr = natoq(fstart, p);}
 	goto st75;
 st75:
 	if ( ++p == pe )
 		goto _test_eof75;
 case 75:
-#line 2256 "mod/silverbox/memcached.c"
+#line 2276 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr122;
 	goto st0;
 tr120:
-#line 504 "mod/silverbox/memcached.rl"
+#line 514 "mod/silverbox/memcached.rl"
 	{incr = natoq(fstart, p);}
 	goto st76;
 st76:
 	if ( ++p == pe )
 		goto _test_eof76;
 case 76:
-#line 2268 "mod/silverbox/memcached.c"
+#line 2288 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2325,14 +2345,14 @@ case 83:
 	}
 	goto st0;
 tr134:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st84;
 st84:
 	if ( ++p == pe )
 		goto _test_eof84;
 case 84:
-#line 2336 "mod/silverbox/memcached.c"
+#line 2356 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2379,7 +2399,7 @@ case 89:
 		goto st0;
 	goto tr140;
 tr140:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2396,7 +2416,7 @@ case 89:
 	if ( ++p == pe )
 		goto _test_eof90;
 case 90:
-#line 2400 "mod/silverbox/memcached.c"
+#line 2420 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2404,7 +2424,7 @@ case 90:
 	}
 	goto st0;
 tr147:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2412,14 +2432,14 @@ case 90:
 		}
 	goto st91;
 tr158:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st91;
 st91:
 	if ( ++p == pe )
 		goto _test_eof91;
 case 91:
-#line 2423 "mod/silverbox/memcached.c"
+#line 2443 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr141;
 	goto st0;
@@ -2437,14 +2457,14 @@ case 92:
 		goto tr144;
 	goto st0;
 tr144:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st93;
 st93:
 	if ( ++p == pe )
 		goto _test_eof93;
 case 93:
-#line 2448 "mod/silverbox/memcached.c"
+#line 2468 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr146;
 		case 13: goto tr147;
@@ -2454,7 +2474,7 @@ case 93:
 		goto st93;
 	goto st0;
 tr148:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2465,7 +2485,7 @@ case 93:
 	if ( ++p == pe )
 		goto _test_eof94;
 case 94:
-#line 2469 "mod/silverbox/memcached.c"
+#line 2489 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2526,14 +2546,14 @@ case 101:
 	}
 	goto st0;
 tr159:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st102;
 st102:
 	if ( ++p == pe )
 		goto _test_eof102;
 case 102:
-#line 2537 "mod/silverbox/memcached.c"
+#line 2557 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2607,18 +2627,18 @@ case 111:
 	}
 	goto st0;
 tr186:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st112;
 tr175:
-#line 505 "mod/silverbox/memcached.rl"
+#line 515 "mod/silverbox/memcached.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st112;
 st112:
 	if ( ++p == pe )
 		goto _test_eof112;
 case 112:
-#line 2622 "mod/silverbox/memcached.c"
+#line 2642 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr169;
 	goto st0;
@@ -2636,14 +2656,14 @@ case 113:
 		goto tr172;
 	goto st0;
 tr172:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st114;
 st114:
 	if ( ++p == pe )
 		goto _test_eof114;
 case 114:
-#line 2647 "mod/silverbox/memcached.c"
+#line 2667 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr174;
 		case 13: goto tr175;
@@ -2653,14 +2673,14 @@ case 114:
 		goto st114;
 	goto st0;
 tr176:
-#line 505 "mod/silverbox/memcached.rl"
+#line 515 "mod/silverbox/memcached.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st115;
 st115:
 	if ( ++p == pe )
 		goto _test_eof115;
 case 115:
-#line 2664 "mod/silverbox/memcached.c"
+#line 2684 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2721,14 +2741,14 @@ case 122:
 	}
 	goto st0;
 tr187:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st123;
 st123:
 	if ( ++p == pe )
 		goto _test_eof123;
 case 123:
-#line 2732 "mod/silverbox/memcached.c"
+#line 2752 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2759,18 +2779,18 @@ case 126:
 	}
 	goto st0;
 tr191:
-#line 547 "mod/silverbox/memcached.rl"
+#line 557 "mod/silverbox/memcached.rl"
 	{show_cas = false;}
 	goto st127;
 tr198:
-#line 548 "mod/silverbox/memcached.rl"
+#line 558 "mod/silverbox/memcached.rl"
 	{show_cas = true;}
 	goto st127;
 st127:
 	if ( ++p == pe )
 		goto _test_eof127;
 case 127:
-#line 2774 "mod/silverbox/memcached.c"
+#line 2794 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st127;
@@ -2779,7 +2799,7 @@ case 127:
 		goto st0;
 	goto tr193;
 tr193:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2796,7 +2816,7 @@ case 127:
 	if ( ++p == pe )
 		goto _test_eof128;
 case 128:
-#line 2800 "mod/silverbox/memcached.c"
+#line 2820 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr195;
 		case 13: goto st129;
@@ -3003,7 +3023,7 @@ case 155:
 		goto st0;
 	goto tr222;
 tr222:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -3020,7 +3040,7 @@ case 155:
 	if ( ++p == pe )
 		goto _test_eof156;
 case 156:
-#line 3024 "mod/silverbox/memcached.c"
+#line 3044 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st157;
 	goto st0;
@@ -3034,49 +3054,49 @@ case 157:
 		goto tr224;
 	goto st0;
 tr224:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st158;
 st158:
 	if ( ++p == pe )
 		goto _test_eof158;
 case 158:
-#line 3045 "mod/silverbox/memcached.c"
+#line 3065 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr225;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st158;
 	goto st0;
 tr225:
-#line 501 "mod/silverbox/memcached.rl"
+#line 511 "mod/silverbox/memcached.rl"
 	{flags = natoq(fstart, p);}
 	goto st159;
 st159:
 	if ( ++p == pe )
 		goto _test_eof159;
 case 159:
-#line 3059 "mod/silverbox/memcached.c"
+#line 3079 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st159;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr228;
 	goto st0;
 tr228:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st160;
 st160:
 	if ( ++p == pe )
 		goto _test_eof160;
 case 160:
-#line 3073 "mod/silverbox/memcached.c"
+#line 3093 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr229;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st160;
 	goto st0;
 tr229:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -3087,21 +3107,21 @@ case 160:
 	if ( ++p == pe )
 		goto _test_eof161;
 case 161:
-#line 3091 "mod/silverbox/memcached.c"
+#line 3111 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st161;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr232;
 	goto st0;
 tr232:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st162;
 st162:
 	if ( ++p == pe )
 		goto _test_eof162;
 case 162:
-#line 3105 "mod/silverbox/memcached.c"
+#line 3125 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr233;
 		case 13: goto tr234;
@@ -3111,30 +3131,30 @@ case 162:
 		goto st162;
 	goto st0;
 tr234:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st163;
 tr247:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st163;
 st163:
 	if ( ++p == pe )
 		goto _test_eof163;
 case 163:
-#line 3126 "mod/silverbox/memcached.c"
+#line 3146 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr237;
 	goto st0;
 tr235:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st164;
 st164:
 	if ( ++p == pe )
 		goto _test_eof164;
 case 164:
-#line 3138 "mod/silverbox/memcached.c"
+#line 3158 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 32: goto st164;
 		case 110: goto st165;
@@ -3226,7 +3246,7 @@ case 175:
 		goto st0;
 	goto tr252;
 tr252:
-#line 478 "mod/silverbox/memcached.rl"
+#line 488 "mod/silverbox/memcached.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -3243,7 +3263,7 @@ case 175:
 	if ( ++p == pe )
 		goto _test_eof176;
 case 176:
-#line 3247 "mod/silverbox/memcached.c"
+#line 3267 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st177;
 	goto st0;
@@ -3257,49 +3277,49 @@ case 177:
 		goto tr254;
 	goto st0;
 tr254:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st178;
 st178:
 	if ( ++p == pe )
 		goto _test_eof178;
 case 178:
-#line 3268 "mod/silverbox/memcached.c"
+#line 3288 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr255;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st178;
 	goto st0;
 tr255:
-#line 501 "mod/silverbox/memcached.rl"
+#line 511 "mod/silverbox/memcached.rl"
 	{flags = natoq(fstart, p);}
 	goto st179;
 st179:
 	if ( ++p == pe )
 		goto _test_eof179;
 case 179:
-#line 3282 "mod/silverbox/memcached.c"
+#line 3302 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st179;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr258;
 	goto st0;
 tr258:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st180;
 st180:
 	if ( ++p == pe )
 		goto _test_eof180;
 case 180:
-#line 3296 "mod/silverbox/memcached.c"
+#line 3316 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto tr259;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st180;
 	goto st0;
 tr259:
-#line 494 "mod/silverbox/memcached.rl"
+#line 504 "mod/silverbox/memcached.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -3310,21 +3330,21 @@ case 180:
 	if ( ++p == pe )
 		goto _test_eof181;
 case 181:
-#line 3314 "mod/silverbox/memcached.c"
+#line 3334 "mod/silverbox/memcached.c"
 	if ( (*p) == 32 )
 		goto st181;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr262;
 	goto st0;
 tr262:
-#line 477 "mod/silverbox/memcached.rl"
+#line 487 "mod/silverbox/memcached.rl"
 	{ fstart = p; }
 	goto st182;
 st182:
 	if ( ++p == pe )
 		goto _test_eof182;
 case 182:
-#line 3328 "mod/silverbox/memcached.c"
+#line 3348 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 10: goto tr263;
 		case 13: goto tr264;
@@ -3334,30 +3354,30 @@ case 182:
 		goto st182;
 	goto st0;
 tr264:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st183;
 tr277:
-#line 536 "mod/silverbox/memcached.rl"
+#line 546 "mod/silverbox/memcached.rl"
 	{ noreply = true; }
 	goto st183;
 st183:
 	if ( ++p == pe )
 		goto _test_eof183;
 case 183:
-#line 3349 "mod/silverbox/memcached.c"
+#line 3369 "mod/silverbox/memcached.c"
 	if ( (*p) == 10 )
 		goto tr267;
 	goto st0;
 tr265:
-#line 502 "mod/silverbox/memcached.rl"
+#line 512 "mod/silverbox/memcached.rl"
 	{bytes = natoq(fstart, p);}
 	goto st184;
 st184:
 	if ( ++p == pe )
 		goto _test_eof184;
 case 184:
-#line 3361 "mod/silverbox/memcached.c"
+#line 3381 "mod/silverbox/memcached.c"
 	switch( (*p) ) {
 		case 32: goto st184;
 		case 110: goto st185;
@@ -3653,7 +3673,7 @@ case 196:
 	_out: {}
 	}
 
-#line 561 "mod/silverbox/memcached.rl"
+#line 571 "mod/silverbox/memcached.rl"
 
 
 	if (!done) {
diff --git a/mod/silverbox/memcached.rl b/mod/silverbox/memcached.rl
index e5dc30d5fc..9f036ca38c 100644
--- a/mod/silverbox/memcached.rl
+++ b/mod/silverbox/memcached.rl
@@ -30,6 +30,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 
+#include <iproto.h>
 #include <salloc.h>
 #include <palloc.h>
 #include <fiber.h>
@@ -239,18 +240,22 @@ memcached_dispatch(struct box_txn *txn)
 
 	say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p);
 
-#define STORE ({							\
-	stats.cmd_set++;						\
-	if (bytes > (1<<20)) {						\
-		add_iov("SERVER_ERROR object too large for cache\r\n", 41); \
-	} else {							\
-		if (store(txn, key, exptime, flags, bytes, data) == 0) { \
-			stats.total_items++;				\
-			add_iov("STORED\r\n", 8);			\
-		} else {						\
-			add_iov("SERVER_ERROR\r\n", 14);		\
-		}							\
-	}								\
+#define STORE ({									\
+	stats.cmd_set++;								\
+	if (bytes > (1<<20)) {								\
+		add_iov("SERVER_ERROR object too large for cache\r\n", 41);		\
+	} else {									\
+		u32 ret_code;								\
+		if ((ret_code = store(txn, key, exptime, flags, bytes, data)) == 0) {	\
+			stats.total_items++;						\
+			add_iov("STORED\r\n", 8);					\
+		} else {								\
+			add_iov("SERVER_ERROR ", 13);					\
+			add_iov(error_codes_desc_strs[ret_code],			\
+				strlen(error_codes_desc_strs[ret_code]));		\
+			add_iov("\r\n", 2);						\
+		}									\
+	}										\
 })
 
 	%%{
@@ -372,10 +377,15 @@ memcached_dispatch(struct box_txn *txn)
 			if (tuple == NULL || tuple->flags & GHOST || expired(tuple)) {
 				add_iov("NOT_FOUND\r\n", 11);
 			} else {
-				if (delete(txn, key) == 0)
+				u32 ret_code;
+				if ((ret_code = delete(txn, key)) == 0)
 					add_iov("DELETED\r\n", 9);
-				else
-					add_iov("SERVER_ERROR\r\n", 14);
+				else {
+					add_iov("SERVER_ERROR ", 13);
+					add_iov(error_codes_desc_strs[ret_code],
+						strlen(error_codes_desc_strs[ret_code]));
+					add_iov("\r\n", 2);
+				}
 			}
 		}
 
-- 
GitLab