diff --git a/core/admin.m b/core/admin.m
index ba6f905c897977820b3b7cc1ed6c983e9fb3d956..336f3139ade0695f96536cd287ba928f906f584f 100644
--- a/core/admin.m
+++ b/core/admin.m
@@ -1464,6 +1464,17 @@ case 107:
 	return fiber_write(out->data, out->len);
 }
 
+/**
+  We need to be able to print from Lua back to the
+ * administrative console. For that, we register this
+ * function as Lua 'print'. However, administrative
+ * console output must be YAML-compatible. If this is
+ * done automatically, the result is ugly, so we don't
+ * do it. A creator of Lua procedures has to do it
+ * herself.  Best we can do here is to add a trailing
+ * \r\n if it's forgotten.
+ */
+
 static int
 lbox_adminprint(struct lua_State *L)
 {
@@ -1482,6 +1493,10 @@ lbox_adminprint(struct lua_State *L)
 static void
 admin_handler(void *data __attribute__((unused)))
 {
+	/*
+	 * Create a disposable Lua interpreter state
+	 * for every new connection.
+	 */
 	lua_State *L = tarantool_lua_init();
 	lua_register(L, "print", lbox_adminprint);
 	@try {
diff --git a/core/fiber.m b/core/fiber.m
index a525e31d1a36a2f010a6e896cf842db60de7ef8f..eab0a32b529d8c754e29f4355ff4ca2806596248 100644
--- a/core/fiber.m
+++ b/core/fiber.m
@@ -693,21 +693,6 @@ fiber_bread(struct tbuf *buf, size_t at_least)
 	return r;
 }
 
-void
-iov_add(const void *buf, size_t len)
-{
-	iov_ensure(1);
-	iov_add_unsafe(buf, len);
-}
-
-void
-iov_dup(const void *buf, size_t len)
-{
-	void *copy = palloc(fiber->gc_pool, len);
-	memcpy(copy, buf, len);
-	iov_add(copy, len);
-}
-
 void
 iov_reset()
 {
diff --git a/include/errcode.h b/include/errcode.h
index c6dfd446d320f91b50ec56a1a000b20d6140533c..f899b2c5891ea9114e88ebea692d41f976568423 100644
--- a/include/errcode.h
+++ b/include/errcode.h
@@ -102,7 +102,7 @@ enum { TNT_ERRMSG_MAX = 512 };
 	/* 45 */_(ER_UNUSED45,			0, "Unused45") \
 	/* 46 */_(ER_UNUSED46,			0, "Unused46") \
 	/* 47 */_(ER_UNUSED47,			0, "Unused47") \
-	/* 48 */_(ER_UNUSED48,			0, "Unused48") \
+	/* 48 */_(ER_PROC_RET,			2, "Return type '%s' is not supported in the binary protocol") \
 	/* 49 */_(ER_TUPLE_NOT_FOUND,		2, "Tuple doesn't exist") \
 	/* 50 */_(ER_NO_SUCH_PROC,		2, "Procedure %.*s is not defined") \
 	/* 51 */_(ER_PROC_LUA,			2, "Lua error: %s") \
diff --git a/include/fiber.h b/include/fiber.h
index d3a2fe780487fc9a42b3f97d99982dab95ff8e3c..5c467eb736665b10e7ad82c334e39f27e7373ad6 100644
--- a/include/fiber.h
+++ b/include/fiber.h
@@ -41,6 +41,7 @@
 #include "third_party/queue.h"
 
 #include "exception.h"
+#include "palloc.h"
 
 #define FIBER_NAME_MAXLEN 32
 
@@ -96,6 +97,10 @@ struct fiber {
 	char name[FIBER_NAME_MAXLEN];
 	void (*f) (void *);
 	void *f_data;
+	/* Store execution context in a fiber. */
+	union {
+		struct box_txn *txn;
+	} mod_data;
 
 	u64 cookie;
 	bool has_peer;
@@ -161,8 +166,19 @@ inline static void iov_ensure(size_t count)
 }
 
 /* Add to fiber's iov vector. */
-void iov_add(const void *buf, size_t len);
-void iov_dup(const void *buf, size_t len);
+inline static void iov_add(const void *buf, size_t len)
+{
+	iov_ensure(1);
+	iov_add_unsafe(buf, len);
+}
+
+inline static void iov_dup(const void *buf, size_t len)
+{
+	void *copy = palloc(fiber->gc_pool, len);
+	memcpy(copy, buf, len);
+	iov_add(copy, len);
+}
+
 /* Reset the fiber's iov vector. */
 ssize_t iov_flush(void);
 /* Write everything in the fiber's iov vector to fiber socket. */
@@ -176,7 +192,6 @@ const char *fiber_peer_name(struct fiber *fiber);
 ssize_t fiber_read(void *buf, size_t count);
 ssize_t fiber_write(const void *buf, size_t count);
 int fiber_close(void);
-ssize_t fiber_flush_output(void);
 void fiber_cleanup(void);
 void fiber_gc(void);
 void fiber_call(struct fiber *callee);
diff --git a/mod/box/box.h b/mod/box/box.h
index edc791bf35736e855628e4d488924c6402beace6..c1392d87c4b19e3a2554ba0bffce8382d68da4bc 100644
--- a/mod/box/box.h
+++ b/mod/box/box.h
@@ -30,6 +30,7 @@
 #include "exception.h"
 #include "iproto.h"
 #include <tbuf.h>
+#include <fiber.h>
 
 struct tarantool_cfg;
 struct box_tuple;
@@ -50,10 +51,20 @@ struct namespace {
 
 extern struct namespace *namespace;
 
+struct box_out {
+	void (*add_u32)(u32 *u32);
+	void (*dup_u32)(u32 u32);
+	void (*add_tuple)(struct box_tuple *tuple);
+};
+
+extern struct box_out box_out_quiet;
+
 struct box_txn {
 	u16 op;
 	u32 flags;
 
+	struct lua_State *L;
+	struct box_out *out;
 	struct namespace *namespace;
 	struct index *index;
 	int n;
@@ -64,21 +75,17 @@ struct box_txn {
 	struct box_tuple *lock_tuple;
 
 	struct tbuf req;
-
-	bool in_recover;
-	bool write_to_wal;
 };
 
 
 #define BOX_RETURN_TUPLE		0x01
 #define BOX_ADD				0x02
 #define BOX_REPLACE			0x04
-#define BOX_QUIET			0x08
 #define BOX_NOT_STORE			0x10
+#define BOX_GC_TXN			0x20
 #define BOX_ALLOWED_REQUEST_FLAGS	(BOX_RETURN_TUPLE | \
 					 BOX_ADD | \
 					 BOX_REPLACE | \
-					 BOX_QUIET | \
 					 BOX_NOT_STORE)
 
 /*
@@ -113,9 +120,11 @@ ENUM(messages, MESSAGES);
 
 extern iproto_callback rw_callback;
 
-/* These 3 are used to implemente memcached 'GET' */
-struct box_txn *txn_alloc(u32 flags);
+/* These are used to implement memcached 'GET' */
+static inline struct box_txn *in_txn() { return fiber->mod_data.txn; }
+struct box_txn *txn_begin();
+void txn_commit(struct box_txn *txn);
+void txn_rollback(struct box_txn *txn);
 void tuple_txn_ref(struct box_txn *txn, struct box_tuple *tuple);
-void txn_cleanup(struct box_txn *txn);
 
 #endif /* TARANTOOL_BOX_H_INCLUDED */
diff --git a/mod/box/box.m b/mod/box/box.m
index 2b79572bc53d44e1299b0fa07189ebc1c6b2f9ff..1bbc68debfcda41883028c71d721b8e0c5ec6e31 100644
--- a/mod/box/box.m
+++ b/mod/box/box.m
@@ -59,9 +59,6 @@ static char status[64] = "unknown";
 static int stat_base;
 STRS(messages, MESSAGES);
 
-/* hooks */
-typedef int (*box_hook_t) (struct box_txn * txn);
-
 /*
   For tuples of size below this threshold, when sending a tuple
   to the client, make a deep copy of the tuple for the duration
@@ -92,8 +89,6 @@ box_snap_row(const struct tbuf *t)
 	return (struct box_snap_row *)t->data;
 }
 
-static void tuple_iov_add(struct box_txn *txn, struct box_tuple *tuple);
-
 static void
 lock_tuple(struct box_txn *txn, struct box_tuple *tuple)
 {
@@ -165,7 +160,7 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data)
 		lock_tuple(txn, txn->tuple);
 		/*
 		 * Mark the tuple as ghost before attempting an
-		 * index replace: if it fails, txn_abort() will
+		 * index replace: if it fails, txn_rollback() will
 		 * look at the flag and remove the tuple.
 		 */
 		txn->tuple->flags |= GHOST;
@@ -183,14 +178,10 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data)
 			index->replace(index, NULL, txn->tuple);
 	}
 
-	if (!(txn->flags & BOX_QUIET)) {
-		u32 tuples_affected = 1;
-
-		iov_dup(&tuples_affected, sizeof(uint32_t));
+	txn->out->dup_u32(1); /* Affected tuples */
 
-		if (txn->flags & BOX_RETURN_TUPLE)
-			tuple_iov_add(txn, txn->tuple);
-	}
+	if (txn->flags & BOX_RETURN_TUPLE)
+		txn->out->add_tuple(txn->tuple);
 }
 
 static void
@@ -433,29 +424,10 @@ prepare_update_fields(struct box_txn *txn, struct tbuf *data)
 		tnt_raise(IllegalParams, :"can't unpack request");
 
 out:
-	if (!(txn->flags & BOX_QUIET)) {
-		iov_dup(&tuples_affected, sizeof(uint32_t));
-
-		if (txn->flags & BOX_RETURN_TUPLE)
-			tuple_iov_add(txn, txn->tuple);
-	}
-}
-
-static void
-tuple_iov_add(struct box_txn *txn, struct box_tuple *tuple)
-{
-	size_t len;
-
-	len = tuple->bsize +
-		field_sizeof(struct box_tuple, bsize) +
-		field_sizeof(struct box_tuple, cardinality);
+	txn->out->dup_u32(tuples_affected);
 
-	if (len > BOX_REF_THRESHOLD) {
-		tuple_txn_ref(txn, tuple);
-		iov_add(&tuple->bsize, len);
-	} else {
-		iov_dup(&tuple->bsize, len);
-	}
+	if (txn->flags & BOX_RETURN_TUPLE)
+		txn->out->add_tuple(txn->tuple);
 }
 
 static void __attribute__((noinline))
@@ -468,7 +440,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data)
 		tnt_raise(IllegalParams, :"tuple count must be positive");
 
 	found = palloc(fiber->gc_pool, sizeof(*found));
-	iov_add(found, sizeof(*found));
+	txn->out->add_u32(found);
 	*found = 0;
 
 	if (txn->index->type == TREE) {
@@ -501,7 +473,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data)
 					continue;
 				}
 
-				tuple_iov_add(txn, tuple);
+				txn->out->add_tuple(tuple);
 
 				if (limit == ++(*found))
 					break;
@@ -528,7 +500,7 @@ process_select(struct box_txn *txn, u32 limit, u32 offset, struct tbuf *data)
 				continue;
 			}
 
-			tuple_iov_add(txn, tuple);
+			txn->out->add_tuple(tuple);
 			(*found)++;
 		}
 	}
@@ -558,12 +530,10 @@ prepare_delete(struct box_txn *txn, void *key)
 		tuples_affected = 1;
 	}
 
-	if (!(txn->flags & BOX_QUIET)) {
-		iov_dup(&tuples_affected, sizeof(tuples_affected));
+	txn->out->dup_u32(tuples_affected);
 
-		if (txn->old_tuple && (txn->flags & BOX_RETURN_TUPLE))
-			tuple_iov_add(txn, txn->old_tuple);
-	}
+	if (txn->old_tuple && (txn->flags & BOX_RETURN_TUPLE))
+		txn->out->add_tuple(txn->old_tuple);
 }
 
 static void
@@ -583,16 +553,58 @@ op_is_select(u32 op)
 	return op == SELECT || op == SELECT_LIMIT;
 }
 
+static void
+iov_add_u32(u32 *p_u32)
+{
+	iov_add(p_u32, sizeof(u32));
+}
+
+static void
+iov_dup_u32(u32 u32)
+{
+	iov_dup(&u32, sizeof(u32));
+}
+
+static void
+iov_add_tuple(struct box_tuple *tuple)
+{
+	size_t len = tuple_len(tuple);
+
+	if (len > BOX_REF_THRESHOLD) {
+		tuple_txn_ref(in_txn(), tuple);
+		iov_add(&tuple->bsize, len);
+	} else {
+		iov_dup(&tuple->bsize, len);
+	}
+}
+
+struct box_out box_out_iproto = {
+	iov_add_u32,
+	iov_dup_u32,
+	iov_add_tuple
+};
+
+static void box_quiet_add_u32(u32 *p_u32 __attribute__((unused))) {}
+static void box_quiet_dup_u32(u32 u32 __attribute__((unused))) {}
+static void box_quiet_add_tuple(struct box_tuple *tuple __attribute__((unused))) {}
+
+struct box_out box_out_quiet = {
+	box_quiet_add_u32,
+	box_quiet_dup_u32,
+	box_quiet_add_tuple
+};
+
 struct box_txn *
-txn_alloc(u32 flags)
+txn_begin()
 {
+	assert(in_txn() == NULL);
 	struct box_txn *txn = p0alloc(fiber->gc_pool, sizeof(*txn));
 	txn->ref_tuples = tbuf_alloc(fiber->gc_pool);
-	txn->flags = flags;
+	assert(fiber->mod_data.txn == NULL);
+	fiber->mod_data.txn = txn;
 	return txn;
 }
 
-
 void txn_assign_n(struct box_txn *txn, struct tbuf *data)
 {
 	txn->n = read_u32(data);
@@ -608,39 +620,17 @@ void txn_assign_n(struct box_txn *txn, struct tbuf *data)
 	txn->index = txn->namespace->index;
 }
 
-/**
-  * Validate the request and start a transaction associated with
-  * that request:
-  *
-  * - parse the request,
-  * - perform a "name resolution", i.e. find the namespace object
-  *   associated with the request.
-  */
-
+/** Remember op code/request in the txn. */
 static void
-txn_begin(struct box_txn *txn, u16 op, struct tbuf *data)
+txn_set_op(struct box_txn *txn, u16 op, struct tbuf *data)
 {
 	txn->op = op;
 	txn->req = (struct tbuf){ .data = data->data, .len = data->len };
 }
 
-void
+static void
 txn_cleanup(struct box_txn *txn)
 {
-	/*
-	 * txn_cleanup() may get called twice in the following
-	 * scenario: Several requests are processed by a single
-	 * iproto loop iteration. The first few requests are
-	 * handled successfully, but the next one fails with an
-	 * OOM. In this case, fiber performs fiber_cleanup() for
-	 * every registered callback. We should not run
-	 * txn_cleanup() twice.
-	 */
-	if (txn->op == 0)
-		return;
-
-	unlock_tuples(txn);
-
 	struct box_tuple **tuple = txn->ref_tuples->data;
 	int i = txn->ref_tuples->len / sizeof(struct box_txn *);
 
@@ -653,11 +643,12 @@ txn_cleanup(struct box_txn *txn)
 	memset(txn, 0, sizeof(*txn));
 }
 
-static void
+void
 txn_commit(struct box_txn *txn)
 {
-	if (txn->op == 0)
-		return;
+	assert(txn == in_txn());
+	assert(txn->op);
+	fiber->mod_data.txn = 0;
 
 	if (!op_is_select(txn->op)) {
 		say_debug("box_commit(op:%s)", messages_strs[txn->op]);
@@ -686,20 +677,22 @@ txn_commit(struct box_txn *txn)
 			commit_replace(txn);
 	}
 
-	if (txn->flags & BOX_QUIET)
-		txn_cleanup(txn);
-	else
+	if (txn->flags & BOX_GC_TXN)
 		fiber_register_cleanup((fiber_cleanup_handler)txn_cleanup, txn);
+	else
+		txn_cleanup(txn);
 }
 
-static void
-txn_abort(struct box_txn *txn)
+void
+txn_rollback(struct box_txn *txn)
 {
+	assert(txn == in_txn());
+	fiber->mod_data.txn = 0;
 	if (txn->op == 0)
 		return;
 
 	if (!op_is_select(txn->op)) {
-		say_debug("box_rollback(op:%s)", messages_strs[txn->op]);
+		say_debug("txn_rollback(op:%s)", messages_strs[txn->op]);
 
 		unlock_tuples(txn);
 
@@ -992,20 +985,27 @@ namespace_init(void)
 	memcached_namespace_init();
 }
 
-void
-box_process(struct box_txn *txn, u32 op, struct tbuf *request_data)
+static void
+box_process_rw(u32 op, struct tbuf *request_data)
 {
 	ev_tstamp start = ev_now(), stop;
 
 	stat_collect(stat_base, op, 1);
 
+	struct box_txn *txn = in_txn();
+	if (txn == NULL) {
+		txn = txn_begin();
+		txn->flags |= BOX_GC_TXN;
+		txn->out = &box_out_iproto;
+	}
+
 	@try {
-		txn_begin(txn, op, request_data);
+		txn_set_op(txn, op, request_data);
 		box_dispatch(txn, request_data);
 		txn_commit(txn);
 	}
 	@catch (id e) {
-		txn_abort(txn);
+		txn_rollback(txn);
 		@throw;
 	}
 	@finally {
@@ -1018,19 +1018,16 @@ box_process(struct box_txn *txn, u32 op, struct tbuf *request_data)
 static void
 box_process_ro(u32 op, struct tbuf *request_data)
 {
-	if (!op_is_select(op))
+	if (!op_is_select(op)) {
+		struct box_txn *txn = in_txn();
+		if (txn != NULL)
+			txn_rollback(txn);
 		tnt_raise(LoggedError, :ER_NONMASTER);
+	}
 
-	return box_process(txn_alloc(0), op, request_data);
-}
-
-static void
-box_process_rw(u32 op, struct tbuf *request_data)
-{
-	return box_process(txn_alloc(0), op, request_data);
+	return box_process_rw(op, request_data);
 }
 
-
 static struct tbuf *
 convert_snap_row_to_wal(struct tbuf *t)
 {
@@ -1051,9 +1048,6 @@ convert_snap_row_to_wal(struct tbuf *t)
 static int
 recover_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t)
 {
-	struct box_txn *txn = txn_alloc(BOX_QUIET | BOX_NOT_STORE);
-	u16 op;
-
 	/* drop wal header */
 	if (tbuf_peek(t, sizeof(struct row_v11)) == NULL)
 		return -1;
@@ -1067,10 +1061,14 @@ recover_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t)
 		return -1;
 	}
 
-	op = read_u16(t);
+	u16 op = read_u16(t);
+
+	struct box_txn *txn = txn_begin();
+	txn->flags |= BOX_NOT_STORE;
+	txn->out = &box_out_quiet;
 
 	@try {
-		box_process(txn, op, t);
+		box_process_rw(op, t);
 	}
 	@catch (id e) {
 		return -1;
diff --git a/mod/box/memcached-grammar.m b/mod/box/memcached-grammar.m
index 886d2d9e24549b7cbb71a3bdd3180fccc51e3384..c8073a479a4e1a5e5b623fc2c428eaec505592d5 100644
--- a/mod/box/memcached-grammar.m
+++ b/mod/box/memcached-grammar.m
@@ -127,7 +127,7 @@ case 5:
 		goto st0;
 	goto tr15;
 tr15:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -158,7 +158,7 @@ case 7:
 		goto tr17;
 	goto st0;
 tr17:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st8;
 st8:
@@ -172,7 +172,7 @@ case 8:
 		goto st8;
 	goto st0;
 tr18:
-#line 312 "mod/box/memcached-grammar.rl"
+#line 250 "mod/box/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st9;
 st9:
@@ -186,7 +186,7 @@ case 9:
 		goto tr21;
 	goto st0;
 tr21:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st10;
 st10:
@@ -200,7 +200,7 @@ case 10:
 		goto st10;
 	goto st0;
 tr22:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -218,7 +218,7 @@ case 11:
 		goto tr25;
 	goto st0;
 tr25:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st12;
 st12:
@@ -235,11 +235,11 @@ case 12:
 		goto st12;
 	goto st0;
 tr26:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -260,7 +260,7 @@ tr26:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -277,9 +277,9 @@ tr26:
 		}
 	goto st197;
 tr30:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -300,7 +300,7 @@ tr30:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -317,11 +317,11 @@ tr30:
 		}
 	goto st197;
 tr39:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -342,7 +342,7 @@ tr39:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -359,11 +359,11 @@ tr39:
 		}
 	goto st197;
 tr58:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -384,7 +384,7 @@ tr58:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -419,9 +419,9 @@ tr58:
 		}
 	goto st197;
 tr62:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -442,7 +442,7 @@ tr62:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -477,11 +477,11 @@ tr62:
 		}
 	goto st197;
 tr71:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -502,7 +502,7 @@ tr71:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -537,11 +537,11 @@ tr71:
 		}
 	goto st197;
 tr91:
-#line 314 "mod/box/memcached-grammar.rl"
+#line 252 "mod/box/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -562,7 +562,7 @@ tr91:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -581,9 +581,9 @@ tr91:
 		}
 	goto st197;
 tr95:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -604,7 +604,7 @@ tr95:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -623,11 +623,11 @@ tr95:
 		}
 	goto st197;
 tr105:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -648,7 +648,7 @@ tr105:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -667,11 +667,11 @@ tr105:
 		}
 	goto st197;
 tr118:
-#line 315 "mod/box/memcached-grammar.rl"
+#line 253 "mod/box/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -734,9 +734,9 @@ tr118:
 		}
 	goto st197;
 tr122:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -799,11 +799,11 @@ tr122:
 		}
 	goto st197;
 tr132:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -866,9 +866,9 @@ tr132:
 		}
 	goto st197;
 tr141:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -894,15 +894,15 @@ tr141:
 		}
 	goto st197;
 tr146:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
 				exptime = exptime + ev_now();
 		}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -928,11 +928,11 @@ tr146:
 		}
 	goto st197;
 tr157:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -958,15 +958,15 @@ tr157:
 		}
 	goto st197;
 tr169:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 270 "mod/box/memcached-grammar.rl"
+#line 208 "mod/box/memcached-grammar.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -978,17 +978,17 @@ tr169:
 		}
 	goto st197;
 tr174:
-#line 316 "mod/box/memcached-grammar.rl"
+#line 254 "mod/box/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 270 "mod/box/memcached-grammar.rl"
+#line 208 "mod/box/memcached-grammar.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -1000,17 +1000,17 @@ tr174:
 		}
 	goto st197;
 tr185:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 270 "mod/box/memcached-grammar.rl"
+#line 208 "mod/box/memcached-grammar.rl"
 	{
 			if (flush_delay > 0) {
 				struct fiber *f = fiber_create("flush_all", -1, -1, flush_all, (void *)flush_delay);
@@ -1022,9 +1022,9 @@ tr185:
 		}
 	goto st197;
 tr195:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1032,103 +1032,41 @@ tr195:
 		}
 #line 192 "mod/box/memcached-grammar.rl"
 	{
-			struct box_txn *txn = txn_alloc(BOX_QUIET);
-			txn->op = SELECT;
-			fiber_register_cleanup((void *)txn_cleanup, txn);
-			stat_collect(stat_base, MEMC_GET, 1);
-			stats.cmd_get++;
-			say_debug("ensuring space for %"PRI_SZ" keys", keys_count);
-			iov_ensure(keys_count * 5 + 1);
-			while (keys_count-- > 0) {
-				struct box_tuple *tuple;
-				struct meta *m;
-				void *field;
-				void *value;
-				void *suffix;
-				u32 key_len;
-				u32 value_len;
-				u32 suffix_len;
-				u32 _l;
-
-				key = read_field(keys);
-				tuple = find(key);
-				key_len = load_varint32(&key);
-
-				if (tuple == NULL || tuple->flags & GHOST) {
-					stat_collect(stat_base, MEMC_GET_MISS, 1);
-					stats.get_misses++;
-					continue;
-				}
-
-				field = tuple->data;
-
-				/* skip key */
-				_l = load_varint32(&field);
-				field += _l;
-
-				/* metainfo */
-				_l = load_varint32(&field);
-				m = field;
-				field += _l;
-
-				/* suffix */
-				suffix_len = load_varint32(&field);
-				suffix = field;
-				field += suffix_len;
-
-				/* value */
-				value_len = load_varint32(&field);
-				value = field;
-
-				if (m->exptime > 0 && m->exptime < ev_now()) {
-					stats.get_misses++;
-					stat_collect(stat_base, MEMC_GET_MISS, 1);
-					continue;
-				} else {
-					stats.get_hits++;
-					stat_collect(stat_base, MEMC_GET_HIT, 1);
-				}
-
-				tuple_txn_ref(txn, tuple);
-
-				if (show_cas) {
-					struct tbuf *b = tbuf_alloc(fiber->gc_pool);
-					tbuf_printf(b, "VALUE %.*s %"PRIu32" %"PRIu32" %"PRIu64"\r\n", key_len, (u8 *)key, m->flags, value_len, m->cas);
-					iov_add_unsafe(b->data, b->len);
-					stats.bytes_written += b->len;
-				} else {
-					iov_add_unsafe("VALUE ", 6);
-					iov_add_unsafe(key, key_len);
-					iov_add_unsafe(suffix, suffix_len);
-				}
-				iov_add_unsafe(value, value_len);
-				iov_add_unsafe("\r\n", 2);
-				stats.bytes_written += value_len + 2;
+			struct box_txn *txn = txn_begin();
+			txn->flags |= BOX_GC_TXN;
+			txn->out = &box_out_quiet;
+			@try {
+				memcached_get(txn, keys_count, keys, show_cas);
+				txn_commit(txn);
+			} @catch (ClientError *e) {
+				txn_rollback(txn);
+				iov_reset();
+				iov_add("SERVER_ERROR ", 13);
+				iov_add(e->errmsg, strlen(e->errmsg));
+				iov_add("\r\n", 2);
 			}
-			iov_add_unsafe("END\r\n", 5);
-			stats.bytes_written += 5;
 		}
 	goto st197;
 tr213:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 284 "mod/box/memcached-grammar.rl"
+#line 222 "mod/box/memcached-grammar.rl"
 	{
 			return 0;
 		}
 	goto st197;
 tr233:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1149,7 +1087,7 @@ tr233:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1166,9 +1104,9 @@ tr233:
 		}
 	goto st197;
 tr237:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1189,7 +1127,7 @@ tr237:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1206,11 +1144,11 @@ tr237:
 		}
 	goto st197;
 tr246:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1231,7 +1169,7 @@ tr246:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1248,11 +1186,11 @@ tr246:
 		}
 	goto st197;
 tr263:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1273,7 +1211,7 @@ tr263:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1286,9 +1224,9 @@ tr263:
 		}
 	goto st197;
 tr267:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1309,7 +1247,7 @@ tr267:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1322,11 +1260,11 @@ tr267:
 		}
 	goto st197;
 tr276:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 318 "mod/box/memcached-grammar.rl"
+#line 256 "mod/box/memcached-grammar.rl"
 	{
 			size_t parsed = p - (u8 *)fiber->rbuf->data;
 			while (fiber->rbuf->len - parsed < bytes + 2) {
@@ -1347,7 +1285,7 @@ tr276:
 				goto exit;
 			}
 		}
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
@@ -1360,15 +1298,15 @@ tr276:
 		}
 	goto st197;
 tr281:
-#line 345 "mod/box/memcached-grammar.rl"
+#line 283 "mod/box/memcached-grammar.rl"
 	{ p++; }
-#line 339 "mod/box/memcached-grammar.rl"
+#line 277 "mod/box/memcached-grammar.rl"
 	{
 			done = true;
 			stats.bytes_read += p - (u8 *)fiber->rbuf->data;
 			tbuf_peek(fiber->rbuf, p - (u8 *)fiber->rbuf->data);
 		}
-#line 280 "mod/box/memcached-grammar.rl"
+#line 218 "mod/box/memcached-grammar.rl"
 	{
 			print_stats();
 		}
@@ -1377,33 +1315,33 @@ st197:
 	if ( ++p == pe )
 		goto _test_eof197;
 case 197:
-#line 1381 "mod/box/memcached-grammar.m"
+#line 1319 "mod/box/memcached-grammar.m"
 	goto st0;
 tr27:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st13;
 tr40:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st13;
 st13:
 	if ( ++p == pe )
 		goto _test_eof13;
 case 13:
-#line 1395 "mod/box/memcached-grammar.m"
+#line 1333 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr30;
 	goto st0;
 tr28:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st14;
 st14:
 	if ( ++p == pe )
 		goto _test_eof14;
 case 14:
-#line 1407 "mod/box/memcached-grammar.m"
+#line 1345 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 32: goto st14;
 		case 110: goto st15;
@@ -1496,18 +1434,18 @@ case 26:
 		goto tr45;
 	goto st0;
 tr45:
-#line 353 "mod/box/memcached-grammar.rl"
+#line 291 "mod/box/memcached-grammar.rl"
 	{append = true; }
 	goto st27;
 tr209:
-#line 354 "mod/box/memcached-grammar.rl"
+#line 292 "mod/box/memcached-grammar.rl"
 	{append = false;}
 	goto st27;
 st27:
 	if ( ++p == pe )
 		goto _test_eof27;
 case 27:
-#line 1511 "mod/box/memcached-grammar.m"
+#line 1449 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st27;
@@ -1516,7 +1454,7 @@ case 27:
 		goto st0;
 	goto tr46;
 tr46:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1533,7 +1471,7 @@ st28:
 	if ( ++p == pe )
 		goto _test_eof28;
 case 28:
-#line 1537 "mod/box/memcached-grammar.m"
+#line 1475 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st29;
 	goto st0;
@@ -1547,49 +1485,49 @@ case 29:
 		goto tr49;
 	goto st0;
 tr49:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st30;
 st30:
 	if ( ++p == pe )
 		goto _test_eof30;
 case 30:
-#line 1558 "mod/box/memcached-grammar.m"
+#line 1496 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr50;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st30;
 	goto st0;
 tr50:
-#line 312 "mod/box/memcached-grammar.rl"
+#line 250 "mod/box/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st31;
 st31:
 	if ( ++p == pe )
 		goto _test_eof31;
 case 31:
-#line 1572 "mod/box/memcached-grammar.m"
+#line 1510 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st31;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr53;
 	goto st0;
 tr53:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st32;
 st32:
 	if ( ++p == pe )
 		goto _test_eof32;
 case 32:
-#line 1586 "mod/box/memcached-grammar.m"
+#line 1524 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr54;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st32;
 	goto st0;
 tr54:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1600,21 +1538,21 @@ st33:
 	if ( ++p == pe )
 		goto _test_eof33;
 case 33:
-#line 1604 "mod/box/memcached-grammar.m"
+#line 1542 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st33;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr57;
 	goto st0;
 tr57:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st34;
 st34:
 	if ( ++p == pe )
 		goto _test_eof34;
 case 34:
-#line 1618 "mod/box/memcached-grammar.m"
+#line 1556 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr58;
 		case 13: goto tr59;
@@ -1624,30 +1562,30 @@ case 34:
 		goto st34;
 	goto st0;
 tr59:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st35;
 tr72:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st35;
 st35:
 	if ( ++p == pe )
 		goto _test_eof35;
 case 35:
-#line 1639 "mod/box/memcached-grammar.m"
+#line 1577 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr62;
 	goto st0;
 tr60:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st36;
 st36:
 	if ( ++p == pe )
 		goto _test_eof36;
 case 36:
-#line 1651 "mod/box/memcached-grammar.m"
+#line 1589 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 32: goto st36;
 		case 110: goto st37;
@@ -1737,7 +1675,7 @@ case 47:
 		goto st0;
 	goto tr76;
 tr76:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -1754,7 +1692,7 @@ st48:
 	if ( ++p == pe )
 		goto _test_eof48;
 case 48:
-#line 1758 "mod/box/memcached-grammar.m"
+#line 1696 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st49;
 	goto st0;
@@ -1768,49 +1706,49 @@ case 49:
 		goto tr78;
 	goto st0;
 tr78:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st50;
 st50:
 	if ( ++p == pe )
 		goto _test_eof50;
 case 50:
-#line 1779 "mod/box/memcached-grammar.m"
+#line 1717 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr79;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st50;
 	goto st0;
 tr79:
-#line 312 "mod/box/memcached-grammar.rl"
+#line 250 "mod/box/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st51;
 st51:
 	if ( ++p == pe )
 		goto _test_eof51;
 case 51:
-#line 1793 "mod/box/memcached-grammar.m"
+#line 1731 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st51;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr82;
 	goto st0;
 tr82:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st52;
 st52:
 	if ( ++p == pe )
 		goto _test_eof52;
 case 52:
-#line 1807 "mod/box/memcached-grammar.m"
+#line 1745 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr83;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st52;
 	goto st0;
 tr83:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -1821,49 +1759,49 @@ st53:
 	if ( ++p == pe )
 		goto _test_eof53;
 case 53:
-#line 1825 "mod/box/memcached-grammar.m"
+#line 1763 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st53;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr86;
 	goto st0;
 tr86:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st54;
 st54:
 	if ( ++p == pe )
 		goto _test_eof54;
 case 54:
-#line 1839 "mod/box/memcached-grammar.m"
+#line 1777 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr87;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st54;
 	goto st0;
 tr87:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st55;
 st55:
 	if ( ++p == pe )
 		goto _test_eof55;
 case 55:
-#line 1853 "mod/box/memcached-grammar.m"
+#line 1791 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st55;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr90;
 	goto st0;
 tr90:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st56;
 st56:
 	if ( ++p == pe )
 		goto _test_eof56;
 case 56:
-#line 1867 "mod/box/memcached-grammar.m"
+#line 1805 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr91;
 		case 13: goto tr92;
@@ -1873,30 +1811,30 @@ case 56:
 		goto st56;
 	goto st0;
 tr106:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st57;
 tr92:
-#line 314 "mod/box/memcached-grammar.rl"
+#line 252 "mod/box/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
 	goto st57;
 st57:
 	if ( ++p == pe )
 		goto _test_eof57;
 case 57:
-#line 1888 "mod/box/memcached-grammar.m"
+#line 1826 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr95;
 	goto st0;
 tr93:
-#line 314 "mod/box/memcached-grammar.rl"
+#line 252 "mod/box/memcached-grammar.rl"
 	{cas = natoq(fstart, p);}
 	goto st58;
 st58:
 	if ( ++p == pe )
 		goto _test_eof58;
 case 58:
-#line 1900 "mod/box/memcached-grammar.m"
+#line 1838 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -1957,14 +1895,14 @@ case 65:
 	}
 	goto st0;
 tr107:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st66;
 st66:
 	if ( ++p == pe )
 		goto _test_eof66;
 case 66:
-#line 1968 "mod/box/memcached-grammar.m"
+#line 1906 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr95;
 		case 13: goto st57;
@@ -2002,18 +1940,18 @@ case 70:
 		goto tr113;
 	goto st0;
 tr113:
-#line 362 "mod/box/memcached-grammar.rl"
+#line 300 "mod/box/memcached-grammar.rl"
 	{incr_sign = -1;}
 	goto st71;
 tr202:
-#line 361 "mod/box/memcached-grammar.rl"
+#line 299 "mod/box/memcached-grammar.rl"
 	{incr_sign = 1; }
 	goto st71;
 st71:
 	if ( ++p == pe )
 		goto _test_eof71;
 case 71:
-#line 2017 "mod/box/memcached-grammar.m"
+#line 1955 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st71;
@@ -2022,7 +1960,7 @@ case 71:
 		goto st0;
 	goto tr114;
 tr114:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2039,7 +1977,7 @@ st72:
 	if ( ++p == pe )
 		goto _test_eof72;
 case 72:
-#line 2043 "mod/box/memcached-grammar.m"
+#line 1981 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st73;
 	goto st0;
@@ -2053,14 +1991,14 @@ case 73:
 		goto tr117;
 	goto st0;
 tr117:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st74;
 st74:
 	if ( ++p == pe )
 		goto _test_eof74;
 case 74:
-#line 2064 "mod/box/memcached-grammar.m"
+#line 2002 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr118;
 		case 13: goto tr119;
@@ -2070,30 +2008,30 @@ case 74:
 		goto st74;
 	goto st0;
 tr133:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st75;
 tr119:
-#line 315 "mod/box/memcached-grammar.rl"
+#line 253 "mod/box/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
 	goto st75;
 st75:
 	if ( ++p == pe )
 		goto _test_eof75;
 case 75:
-#line 2085 "mod/box/memcached-grammar.m"
+#line 2023 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr122;
 	goto st0;
 tr120:
-#line 315 "mod/box/memcached-grammar.rl"
+#line 253 "mod/box/memcached-grammar.rl"
 	{incr = natoq(fstart, p);}
 	goto st76;
 st76:
 	if ( ++p == pe )
 		goto _test_eof76;
 case 76:
-#line 2097 "mod/box/memcached-grammar.m"
+#line 2035 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2154,14 +2092,14 @@ case 83:
 	}
 	goto st0;
 tr134:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st84;
 st84:
 	if ( ++p == pe )
 		goto _test_eof84;
 case 84:
-#line 2165 "mod/box/memcached-grammar.m"
+#line 2103 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr122;
 		case 13: goto st75;
@@ -2208,7 +2146,7 @@ case 89:
 		goto st0;
 	goto tr140;
 tr140:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2225,7 +2163,7 @@ st90:
 	if ( ++p == pe )
 		goto _test_eof90;
 case 90:
-#line 2229 "mod/box/memcached-grammar.m"
+#line 2167 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2233,7 +2171,7 @@ case 90:
 	}
 	goto st0;
 tr147:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2241,14 +2179,14 @@ tr147:
 		}
 	goto st91;
 tr158:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st91;
 st91:
 	if ( ++p == pe )
 		goto _test_eof91;
 case 91:
-#line 2252 "mod/box/memcached-grammar.m"
+#line 2190 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr141;
 	goto st0;
@@ -2266,14 +2204,14 @@ case 92:
 		goto tr144;
 	goto st0;
 tr144:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st93;
 st93:
 	if ( ++p == pe )
 		goto _test_eof93;
 case 93:
-#line 2277 "mod/box/memcached-grammar.m"
+#line 2215 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr146;
 		case 13: goto tr147;
@@ -2283,7 +2221,7 @@ case 93:
 		goto st93;
 	goto st0;
 tr148:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2294,7 +2232,7 @@ st94:
 	if ( ++p == pe )
 		goto _test_eof94;
 case 94:
-#line 2298 "mod/box/memcached-grammar.m"
+#line 2236 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2355,14 +2293,14 @@ case 101:
 	}
 	goto st0;
 tr159:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st102;
 st102:
 	if ( ++p == pe )
 		goto _test_eof102;
 case 102:
-#line 2366 "mod/box/memcached-grammar.m"
+#line 2304 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr141;
 		case 13: goto st91;
@@ -2436,18 +2374,18 @@ case 111:
 	}
 	goto st0;
 tr186:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st112;
 tr175:
-#line 316 "mod/box/memcached-grammar.rl"
+#line 254 "mod/box/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st112;
 st112:
 	if ( ++p == pe )
 		goto _test_eof112;
 case 112:
-#line 2451 "mod/box/memcached-grammar.m"
+#line 2389 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr169;
 	goto st0;
@@ -2465,14 +2403,14 @@ case 113:
 		goto tr172;
 	goto st0;
 tr172:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st114;
 st114:
 	if ( ++p == pe )
 		goto _test_eof114;
 case 114:
-#line 2476 "mod/box/memcached-grammar.m"
+#line 2414 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr174;
 		case 13: goto tr175;
@@ -2482,14 +2420,14 @@ case 114:
 		goto st114;
 	goto st0;
 tr176:
-#line 316 "mod/box/memcached-grammar.rl"
+#line 254 "mod/box/memcached-grammar.rl"
 	{flush_delay = natoq(fstart, p);}
 	goto st115;
 st115:
 	if ( ++p == pe )
 		goto _test_eof115;
 case 115:
-#line 2493 "mod/box/memcached-grammar.m"
+#line 2431 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2550,14 +2488,14 @@ case 122:
 	}
 	goto st0;
 tr187:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st123;
 st123:
 	if ( ++p == pe )
 		goto _test_eof123;
 case 123:
-#line 2561 "mod/box/memcached-grammar.m"
+#line 2499 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr169;
 		case 13: goto st112;
@@ -2588,18 +2526,18 @@ case 126:
 	}
 	goto st0;
 tr191:
-#line 358 "mod/box/memcached-grammar.rl"
+#line 296 "mod/box/memcached-grammar.rl"
 	{show_cas = false;}
 	goto st127;
 tr198:
-#line 359 "mod/box/memcached-grammar.rl"
+#line 297 "mod/box/memcached-grammar.rl"
 	{show_cas = true;}
 	goto st127;
 st127:
 	if ( ++p == pe )
 		goto _test_eof127;
 case 127:
-#line 2603 "mod/box/memcached-grammar.m"
+#line 2541 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 13: goto st0;
 		case 32: goto st127;
@@ -2608,7 +2546,7 @@ case 127:
 		goto st0;
 	goto tr193;
 tr193:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2625,7 +2563,7 @@ st128:
 	if ( ++p == pe )
 		goto _test_eof128;
 case 128:
-#line 2629 "mod/box/memcached-grammar.m"
+#line 2567 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr195;
 		case 13: goto st129;
@@ -2832,7 +2770,7 @@ case 155:
 		goto st0;
 	goto tr222;
 tr222:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -2849,7 +2787,7 @@ st156:
 	if ( ++p == pe )
 		goto _test_eof156;
 case 156:
-#line 2853 "mod/box/memcached-grammar.m"
+#line 2791 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st157;
 	goto st0;
@@ -2863,49 +2801,49 @@ case 157:
 		goto tr224;
 	goto st0;
 tr224:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st158;
 st158:
 	if ( ++p == pe )
 		goto _test_eof158;
 case 158:
-#line 2874 "mod/box/memcached-grammar.m"
+#line 2812 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr225;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st158;
 	goto st0;
 tr225:
-#line 312 "mod/box/memcached-grammar.rl"
+#line 250 "mod/box/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st159;
 st159:
 	if ( ++p == pe )
 		goto _test_eof159;
 case 159:
-#line 2888 "mod/box/memcached-grammar.m"
+#line 2826 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st159;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr228;
 	goto st0;
 tr228:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st160;
 st160:
 	if ( ++p == pe )
 		goto _test_eof160;
 case 160:
-#line 2902 "mod/box/memcached-grammar.m"
+#line 2840 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr229;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st160;
 	goto st0;
 tr229:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -2916,21 +2854,21 @@ st161:
 	if ( ++p == pe )
 		goto _test_eof161;
 case 161:
-#line 2920 "mod/box/memcached-grammar.m"
+#line 2858 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st161;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr232;
 	goto st0;
 tr232:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st162;
 st162:
 	if ( ++p == pe )
 		goto _test_eof162;
 case 162:
-#line 2934 "mod/box/memcached-grammar.m"
+#line 2872 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr233;
 		case 13: goto tr234;
@@ -2940,30 +2878,30 @@ case 162:
 		goto st162;
 	goto st0;
 tr234:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st163;
 tr247:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st163;
 st163:
 	if ( ++p == pe )
 		goto _test_eof163;
 case 163:
-#line 2955 "mod/box/memcached-grammar.m"
+#line 2893 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr237;
 	goto st0;
 tr235:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st164;
 st164:
 	if ( ++p == pe )
 		goto _test_eof164;
 case 164:
-#line 2967 "mod/box/memcached-grammar.m"
+#line 2905 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 32: goto st164;
 		case 110: goto st165;
@@ -3055,7 +2993,7 @@ case 175:
 		goto st0;
 	goto tr252;
 tr252:
-#line 289 "mod/box/memcached-grammar.rl"
+#line 227 "mod/box/memcached-grammar.rl"
 	{
 			fstart = p;
 			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
@@ -3072,7 +3010,7 @@ st176:
 	if ( ++p == pe )
 		goto _test_eof176;
 case 176:
-#line 3076 "mod/box/memcached-grammar.m"
+#line 3014 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st177;
 	goto st0;
@@ -3086,49 +3024,49 @@ case 177:
 		goto tr254;
 	goto st0;
 tr254:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st178;
 st178:
 	if ( ++p == pe )
 		goto _test_eof178;
 case 178:
-#line 3097 "mod/box/memcached-grammar.m"
+#line 3035 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr255;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st178;
 	goto st0;
 tr255:
-#line 312 "mod/box/memcached-grammar.rl"
+#line 250 "mod/box/memcached-grammar.rl"
 	{flags = natoq(fstart, p);}
 	goto st179;
 st179:
 	if ( ++p == pe )
 		goto _test_eof179;
 case 179:
-#line 3111 "mod/box/memcached-grammar.m"
+#line 3049 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st179;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr258;
 	goto st0;
 tr258:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st180;
 st180:
 	if ( ++p == pe )
 		goto _test_eof180;
 case 180:
-#line 3125 "mod/box/memcached-grammar.m"
+#line 3063 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto tr259;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto st180;
 	goto st0;
 tr259:
-#line 305 "mod/box/memcached-grammar.rl"
+#line 243 "mod/box/memcached-grammar.rl"
 	{
 			exptime = natoq(fstart, p);
 			if (exptime > 0 && exptime <= 60*60*24*30)
@@ -3139,21 +3077,21 @@ st181:
 	if ( ++p == pe )
 		goto _test_eof181;
 case 181:
-#line 3143 "mod/box/memcached-grammar.m"
+#line 3081 "mod/box/memcached-grammar.m"
 	if ( (*p) == 32 )
 		goto st181;
 	if ( 48 <= (*p) && (*p) <= 57 )
 		goto tr262;
 	goto st0;
 tr262:
-#line 288 "mod/box/memcached-grammar.rl"
+#line 226 "mod/box/memcached-grammar.rl"
 	{ fstart = p; }
 	goto st182;
 st182:
 	if ( ++p == pe )
 		goto _test_eof182;
 case 182:
-#line 3157 "mod/box/memcached-grammar.m"
+#line 3095 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 10: goto tr263;
 		case 13: goto tr264;
@@ -3163,30 +3101,30 @@ case 182:
 		goto st182;
 	goto st0;
 tr264:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st183;
 tr277:
-#line 347 "mod/box/memcached-grammar.rl"
+#line 285 "mod/box/memcached-grammar.rl"
 	{ noreply = true; }
 	goto st183;
 st183:
 	if ( ++p == pe )
 		goto _test_eof183;
 case 183:
-#line 3178 "mod/box/memcached-grammar.m"
+#line 3116 "mod/box/memcached-grammar.m"
 	if ( (*p) == 10 )
 		goto tr267;
 	goto st0;
 tr265:
-#line 313 "mod/box/memcached-grammar.rl"
+#line 251 "mod/box/memcached-grammar.rl"
 	{bytes = natoq(fstart, p);}
 	goto st184;
 st184:
 	if ( ++p == pe )
 		goto _test_eof184;
 case 184:
-#line 3190 "mod/box/memcached-grammar.m"
+#line 3128 "mod/box/memcached-grammar.m"
 	switch( (*p) ) {
 		case 32: goto st184;
 		case 110: goto st185;
@@ -3482,7 +3420,7 @@ case 196:
 	_out: {}
 	}
 
-#line 372 "mod/box/memcached-grammar.rl"
+#line 310 "mod/box/memcached-grammar.rl"
 
 
 	if (!done) {
diff --git a/mod/box/memcached-grammar.rl b/mod/box/memcached-grammar.rl
index 380982624a697a01d71ab2e64593bc816484cbee..5eb1e5c998226a0d4ef4388d9d69cb84d8613404 100644
--- a/mod/box/memcached-grammar.rl
+++ b/mod/box/memcached-grammar.rl
@@ -190,81 +190,19 @@ memcached_dispatch()
 		}
 
 		action get {
-			struct box_txn *txn = txn_alloc(BOX_QUIET);
-			txn->op = SELECT;
-			fiber_register_cleanup((void *)txn_cleanup, txn);
-			stat_collect(stat_base, MEMC_GET, 1);
-			stats.cmd_get++;
-			say_debug("ensuring space for %"PRI_SZ" keys", keys_count);
-			iov_ensure(keys_count * 5 + 1);
-			while (keys_count-- > 0) {
-				struct box_tuple *tuple;
-				struct meta *m;
-				void *field;
-				void *value;
-				void *suffix;
-				u32 key_len;
-				u32 value_len;
-				u32 suffix_len;
-				u32 _l;
-
-				key = read_field(keys);
-				tuple = find(key);
-				key_len = load_varint32(&key);
-
-				if (tuple == NULL || tuple->flags & GHOST) {
-					stat_collect(stat_base, MEMC_GET_MISS, 1);
-					stats.get_misses++;
-					continue;
-				}
-
-				field = tuple->data;
-
-				/* skip key */
-				_l = load_varint32(&field);
-				field += _l;
-
-				/* metainfo */
-				_l = load_varint32(&field);
-				m = field;
-				field += _l;
-
-				/* suffix */
-				suffix_len = load_varint32(&field);
-				suffix = field;
-				field += suffix_len;
-
-				/* value */
-				value_len = load_varint32(&field);
-				value = field;
-
-				if (m->exptime > 0 && m->exptime < ev_now()) {
-					stats.get_misses++;
-					stat_collect(stat_base, MEMC_GET_MISS, 1);
-					continue;
-				} else {
-					stats.get_hits++;
-					stat_collect(stat_base, MEMC_GET_HIT, 1);
-				}
-
-				tuple_txn_ref(txn, tuple);
-
-				if (show_cas) {
-					struct tbuf *b = tbuf_alloc(fiber->gc_pool);
-					tbuf_printf(b, "VALUE %.*s %"PRIu32" %"PRIu32" %"PRIu64"\r\n", key_len, (u8 *)key, m->flags, value_len, m->cas);
-					iov_add_unsafe(b->data, b->len);
-					stats.bytes_written += b->len;
-				} else {
-					iov_add_unsafe("VALUE ", 6);
-					iov_add_unsafe(key, key_len);
-					iov_add_unsafe(suffix, suffix_len);
-				}
-				iov_add_unsafe(value, value_len);
-				iov_add_unsafe("\r\n", 2);
-				stats.bytes_written += value_len + 2;
+			struct box_txn *txn = txn_begin();
+			txn->flags |= BOX_GC_TXN;
+			txn->out = &box_out_quiet;
+			@try {
+				memcached_get(txn, keys_count, keys, show_cas);
+				txn_commit(txn);
+			} @catch (ClientError *e) {
+				txn_rollback(txn);
+				iov_reset();
+				iov_add("SERVER_ERROR ", 13);
+				iov_add(e->errmsg, strlen(e->errmsg));
+				iov_add("\r\n", 2);
 			}
-			iov_add_unsafe("END\r\n", 5);
-			stats.bytes_written += 5;
 		}
 
 		action flush_all {
diff --git a/mod/box/memcached.m b/mod/box/memcached.m
index 287bf1d28b02f8c812c25ae20b022c452e0737ce..a135b05d3b720c0c769381ae683439fcfaec1f6f 100644
--- a/mod/box/memcached.m
+++ b/mod/box/memcached.m
@@ -68,7 +68,8 @@ natoq(const u8 *start, const u8 *end)
 static void
 store(void *key, u32 exptime, u32 flags, u32 bytes, u8 *data)
 {
-	u32 box_flags = BOX_QUIET, cardinality = 4;
+	u32 box_flags = 0;
+	u32 cardinality = 4;
 	static u64 cas = 42;
 	struct meta m;
 
@@ -97,6 +98,9 @@ store(void *key, u32 exptime, u32 flags, u32 bytes, u8 *data)
 	int key_len = load_varint32(&key);
 	say_debug("memcached/store key:(%i)'%.*s' exptime:%"PRIu32" flags:%"PRIu32" cas:%"PRIu64,
 		  key_len, key_len, (u8 *)key, exptime, flags, cas);
+
+	struct box_txn *txn = txn_begin();
+	txn->out = &box_out_quiet;
 	/*
 	 * Use a box dispatch wrapper which handles correctly
 	 * read-only/read-write modes.
@@ -108,7 +112,7 @@ static void
 delete(void *key)
 {
 	u32 key_len = 1;
-	u32 box_flags = BOX_QUIET;
+	u32 box_flags = 0;
 	struct tbuf *req = tbuf_alloc(fiber->gc_pool);
 
 	tbuf_append(req, &cfg.memcached_namespace, sizeof(u32));
@@ -116,6 +120,9 @@ delete(void *key)
 	tbuf_append(req, &key_len, sizeof(key_len));
 	tbuf_append_field(req, key);
 
+	struct box_txn *txn = txn_begin();
+	txn->out = &box_out_quiet;
+
 	rw_callback(DELETE, req);
 }
 
@@ -192,6 +199,83 @@ print_stats()
 	iov_add(out->data, out->len);
 }
 
+void memcached_get(struct box_txn *txn, size_t keys_count, struct tbuf *keys,
+		   bool show_cas)
+{
+	txn->op = SELECT;
+	stat_collect(stat_base, MEMC_GET, 1);
+	stats.cmd_get++;
+	say_debug("ensuring space for %"PRI_SZ" keys", keys_count);
+	iov_ensure(keys_count * 5 + 1);
+	while (keys_count-- > 0) {
+		struct box_tuple *tuple;
+		struct meta *m;
+		void *field;
+		void *value;
+		void *suffix;
+		u32 key_len;
+		u32 value_len;
+		u32 suffix_len;
+		u32 _l;
+
+		void *key = read_field(keys);
+		tuple = find(key);
+		key_len = load_varint32(&key);
+
+		if (tuple == NULL || tuple->flags & GHOST) {
+			stat_collect(stat_base, MEMC_GET_MISS, 1);
+			stats.get_misses++;
+			continue;
+		}
+
+		field = tuple->data;
+
+		/* skip key */
+		_l = load_varint32(&field);
+		field += _l;
+
+		/* metainfo */
+		_l = load_varint32(&field);
+		m = field;
+		field += _l;
+
+		/* suffix */
+		suffix_len = load_varint32(&field);
+		suffix = field;
+		field += suffix_len;
+
+		/* value */
+		value_len = load_varint32(&field);
+		value = field;
+
+		if (m->exptime > 0 && m->exptime < ev_now()) {
+			stats.get_misses++;
+			stat_collect(stat_base, MEMC_GET_MISS, 1);
+			continue;
+		}
+		stats.get_hits++;
+		stat_collect(stat_base, MEMC_GET_HIT, 1);
+
+		tuple_txn_ref(txn, tuple);
+
+		if (show_cas) {
+			struct tbuf *b = tbuf_alloc(fiber->gc_pool);
+			tbuf_printf(b, "VALUE %.*s %"PRIu32" %"PRIu32" %"PRIu64"\r\n", key_len, (u8 *)key, m->flags, value_len, m->cas);
+			iov_add_unsafe(b->data, b->len);
+			stats.bytes_written += b->len;
+		} else {
+			iov_add_unsafe("VALUE ", 6);
+			iov_add_unsafe(key, key_len);
+			iov_add_unsafe(suffix, suffix_len);
+		}
+		iov_add_unsafe(value, value_len);
+		iov_add_unsafe("\r\n", 2);
+		stats.bytes_written += value_len + 2;
+	}
+	iov_add_unsafe("END\r\n", 5);
+	stats.bytes_written += 5;
+}
+
 static void
 flush_all(void *data)
 {
diff --git a/mod/box/tuple.h b/mod/box/tuple.h
index 15d2f1352e1a0d3ea0d448fcf485d462125a9d77..0a3ed5ca73d0cb76fe1e0a3535de510cd19f67dd 100644
--- a/mod/box/tuple.h
+++ b/mod/box/tuple.h
@@ -92,5 +92,12 @@ tuple_field(struct box_tuple *tuple, size_t i);
  */
 void
 tuple_print(struct tbuf *buf, uint8_t cardinality, void *f);
+
+/** Tuple length when adding to iov. */
+static inline size_t tuple_len(struct box_tuple *tuple)
+{
+	return tuple->bsize + sizeof(tuple->bsize) +
+		sizeof(tuple->cardinality);
+}
 #endif /* TARANTOOL_BOX_TUPLE_H_INCLUDED */
 
diff --git a/test/box_memcached/multiversioning.result b/test/box_memcached/multiversioning.result
index b115dd902be6d6c5dd950fb445c62a289dad82fe..5fccf79ed9a98a086c841b1e2577bdc065b9461b 100644
--- a/test/box_memcached/multiversioning.result
+++ b/test/box_memcached/multiversioning.result
@@ -13,8 +13,8 @@ set big 0 0 262144
 <big-value-upper-case>
 STORED
 
-# recv reply 'get big' from firs memcached client 
-succes: buf == reply
+# recv reply 'get big' from the first memcached client 
+success: buf == reply
 show stat
 ---
 statistics:
diff --git a/test/box_memcached/multiversioning.test b/test/box_memcached/multiversioning.test
index 13a9cf08e02b4840132ac25e796243add2cb63b6..f9f322a4d3069a656923154a97beac4f64bb5b87 100644
--- a/test/box_memcached/multiversioning.test
+++ b/test/box_memcached/multiversioning.test
@@ -22,13 +22,14 @@ print """# Store big in lower case via first memcached client """
 print "set big 0 0 %d\r\n<big-value-upper-case>" % buf_size
 print exec memcached2 silent "set big 0 0 %d\r\n%s\r\n" % (buf_size, buf_upper)
 
-print """# recv reply 'get big' from firs memcached client """
+print """# recv reply 'get big' from the first memcached client """
 reply = recv memcached1 silent
 reply_buf = reply.split('\r\n')[1]
 if buf == reply_buf:
-    print "succes: buf == reply"
+    print "success: buf == reply"
 else:
     print "fail: buf != reply"
+    print len(buf), len(reply_buf)
 
 # resore default suite config
 server.stop()