diff --git a/include/fiber.h b/include/fiber.h
deleted file mode 100644
index 7c391620a3714473840c40a3f1b86b51b1101336..0000000000000000000000000000000000000000
--- a/include/fiber.h
+++ /dev/null
@@ -1,183 +0,0 @@
-#ifndef TARANTOOL_FIBER_H_INCLUDED
-#define TARANTOOL_FIBER_H_INCLUDED
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "tarantool/config.h"
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <tarantool_ev.h>
-#include <coro.h>
-#include <tarantool/util.h>
-#include "third_party/queue.h"
-
-#if defined(__cplusplus)
-#include "exception.h"
-#endif /* defined(__cplusplus) */
-#include "palloc.h"
-#include <rlist.h>
-
-#define FIBER_NAME_MAXLEN PALLOC_POOL_NAME_MAXLEN
-
-#define FIBER_READING_INBOX (1 << 0)
-/** This fiber can be cancelled synchronously. */
-#define FIBER_CANCELLABLE   (1 << 1)
-/** Indicates that a fiber has been cancelled. */
-#define FIBER_CANCEL        (1 << 2)
-/** This fiber was created via stored procedures API. */
-#define FIBER_USER_MODE     (1 << 3)
-/** This fiber was marked as ready for wake up */
-#define FIBER_READY	    (1 << 4)
-
-/** This is thrown by fiber_* API calls when the fiber is
- * cancelled.
- */
-
-#if defined(__cplusplus)
-class FiberCancelException: public Exception {
-public:
-	FiberCancelException(const char *file, unsigned line)
-		: Exception(file, line) {
-		/* Nothing */
-	}
-
-	virtual void log() const {
-		say_debug("FiberCancelException");
-	}
-};
-
-extern "C" {
-#endif /* defined(__cplusplus) */
-
-struct fiber {
-#ifdef ENABLE_BACKTRACE
-	void *last_stack_frame;
-#endif
-	int csw;
-	struct tarantool_coro coro;
-	/* A garbage-collected memory pool. */
-	struct palloc_pool *gc_pool;
-	/** Fiber id. */
-	uint32_t fid;
-	/**
-	 * Session id of the session the fiber is running
-	 * on behalf of. The concept of an associated session
-	 * is similar to the concept of controlling tty
-	 * in a UNIX process. When a fiber is created,
-	 * its sid is 0. If it's running a request on behalf
-	 * of a user connection, it's sid is changed to module-
-	 * generated identifier of the session.
-	 */
-	uint32_t sid;
-
-	struct rlist link;
-	struct rlist state;
-
-	/* This struct is considered as non-POD when compiling by g++.
-	 * You can safetly ignore all offset_of-related warnings.
-	 * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31488
-	 */
-	void (*f) (va_list);
-	va_list f_data;
-	uint32_t flags;
-	struct fiber *waiter;
-	uint64_t cookie;
-};
-
-extern __thread struct fiber *fiber_ptr;
-
-void fiber_init(void);
-void fiber_free(void);
-typedef void(*fiber_func)(va_list);
-struct fiber *fiber_new(const char *name, fiber_func func);
-void fiber_set_name(struct fiber *fiber, const char *name);
-int wait_for_child(pid_t pid);
-
-static inline const char *
-fiber_name(struct fiber *f)
-{
-	return f->gc_pool ? palloc_name(f->gc_pool) : "(none)";
-}
-
-void
-fiber_checkstack();
-
-void fiber_yield(void);
-void fiber_yield_to(struct fiber *f);
-
-/**
- * @brief yield & check for timeout
- * @return true if timeout exceeded
- */
-bool fiber_yield_timeout(ev_tstamp delay);
-
-
-void fiber_destroy_all();
-
-void fiber_gc(void);
-void fiber_call(struct fiber *callee, ...);
-void fiber_wakeup(struct fiber *f);
-struct fiber *fiber_find(uint32_t fid);
-/** Cancel a fiber. A cancelled fiber will have
- * tnt_FiberCancelException raised in it.
- *
- * A fiber can be cancelled only if it is
- * FIBER_CANCELLABLE flag is set.
- */
-void fiber_cancel(struct fiber *f);
-/** Check if the current fiber has been cancelled.  Raises
- * tnt_FiberCancelException
- */
-void fiber_testcancel(void);
-/** Make it possible or not possible to cancel the current
- * fiber.
- *
- * return previous state.
- */
-bool fiber_setcancellable(bool enable);
-void fiber_sleep(ev_tstamp s);
-struct tbuf;
-void fiber_info(struct tbuf *out);
-void fiber_schedule(ev_watcher *watcher, int event __attribute__((unused)));
-
-/**
- * Attach this fiber to a session identified by sid and to a cookie.
- */
-static inline void
-fiber_set_sid(struct fiber *f, uint32_t sid, uint64_t cookie)
-{
-	f->sid = sid;
-	f->cookie = cookie;
-}
-
-#if defined(__cplusplus)
-}
-#endif
-#endif /* TARANTOOL_FIBER_H_INCLUDED */
diff --git a/include/mutex.h b/include/mutex.h
deleted file mode 100644
index cab56463eea8fdda08c650af5e544eef68db8745..0000000000000000000000000000000000000000
--- a/include/mutex.h
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef TARANTOOL_MUTEX_H_INCLUDED
-#define TARANTOOL_MUTEX_H_INCLUDED
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <assert.h>
-#include <rlist.h>
-
-/** Mutex of cooperative multitasking environment. */
-
-struct mutex
-{
-	/**
-	 * The queue of fibers waiting on a mutex.
-	 * The first fiber owns the mutex.
-	 */
-	struct rlist queue;
-};
-
-/**
- * Initialize the given mutex.
- *
- * @param m   mutex to be initialized.
- */
-static inline void
-mutex_create(struct mutex *m)
-{
-	rlist_create(&m->queue);
-}
-
-static inline void
-mutex_destroy(struct mutex *m)
-{
-	while (!rlist_empty(&m->queue)) {
-		struct fiber *f = rlist_first_entry(&m->queue,
-						    struct fiber, state);
-		rlist_del_entry(f, state);
-	}
-}
-
-/**
- * Lock a mutex. If the mutex is already locked by another fiber,
- * waits for timeout.
- *
- * @param m mutex to be locked.
- *
- * @retval false  success
- * @retval true   timeout
- */
-static inline bool
-mutex_lock_timeout(struct mutex *m, ev_tstamp timeout)
-{
-	rlist_add_tail_entry(&m->queue, fiber_ptr, state);
-	ev_tstamp start = timeout;
-	while (timeout > 0) {
-		struct fiber *f = rlist_first_entry(&m->queue,
-						    struct fiber, state);
-		if (f == fiber_ptr)
-			break;
-
-		fiber_yield_timeout(timeout);
-		timeout -= ev_now() - start;
-		if (timeout <= 0) {
-			rlist_del_entry(fiber_ptr, state);
-			errno = ETIMEDOUT;
-			return true;
-		}
-	}
-	return false;
-}
-
-/**
- * Lock a mutex (no timeout). Waits indefinitely until
- * the current fiber can gain access to the mutex.
- */
-static inline void
-mutex_lock(struct mutex *m)
-{
-	(void) mutex_lock_timeout(m, TIMEOUT_INFINITY);
-}
-
-/**
- * Try to lock a mutex. Return immediately if the mutex is locked.
- * @retval false  success
- * @retval true   the mutex is locked.
- */
-static inline bool
-mutex_trylock(struct mutex *m)
-{
-	if (rlist_empty(&m->queue)) {
-		mutex_lock(m);
-		return false;
-	}
-	return true;
-}
-
-/**
- * Unlock a mutex. The fiber calling this function must
- * own the mutex.
- */
-static inline void
-mutex_unlock(struct mutex *m)
-{
-	struct fiber *f;
-	f = rlist_first_entry(&m->queue, struct fiber, state);
-	assert(f == fiber_ptr);
-	rlist_del_entry(f, state);
-	if (!rlist_empty(&m->queue)) {
-		f = rlist_first_entry(&m->queue, struct fiber, state);
-		fiber_wakeup(f);
-	}
-}
-
-#endif /* TARANTOOL_MUTEX_H_INCLUDED */
diff --git a/src/admin.cc b/src/admin.cc
deleted file mode 100644
index 9670a9250b8bd6a49a330899fde18a51156dc4d0..0000000000000000000000000000000000000000
--- a/src/admin.cc
+++ /dev/null
@@ -1,2029 +0,0 @@
-
-#line 1 "src/admin.rl"
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <fiber.h>
-#include <palloc.h>
-#include <salloc.h>
-#include <say.h>
-#include <stat.h>
-#include <tarantool.h>
-#include "lua/init.h"
-#include <recovery.h>
-#include <tbuf.h>
-#include "tarantool/util.h"
-#include <errinj.h>
-#include "coio_buf.h"
-
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-
-#include "box/box.h"
-#include "lua/init.h"
-#include "session.h"
-#include "scoped_guard.h"
-#include "box/space.h"
-
-static const char *help =
-	"available commands:" CRLF
-	" - help" CRLF
-	" - exit" CRLF
-	" - show info" CRLF
-	" - show fiber" CRLF
-	" - show configuration" CRLF
-	" - show index" CRLF
-	" - show slab" CRLF
-	" - show palloc" CRLF
-	" - show stat" CRLF
-	" - save coredump" CRLF
-	" - save snapshot" CRLF
-	" - lua command" CRLF
-	" - reload configuration" CRLF
-	" - show injections (debug mode only)" CRLF
-	" - set injection <name> <state> (debug mode only)" CRLF;
-
-static const char *unknown_command = "unknown command. try typing help." CRLF;
-
-
-#line 84 "src/admin.cc"
-static const int admin_start = 1;
-static const int admin_first_final = 139;
-static const int admin_error = 0;
-
-static const int admin_en_main = 1;
-
-
-#line 83 "src/admin.rl"
-
-
-struct salloc_stat_admin_cb_ctx {
-	int64_t total_used;
-	int64_t total_used_real;
-	int64_t total_alloc_real;
-	struct tbuf *out;
-};
-
-static int
-salloc_stat_admin_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
-{
-	struct salloc_stat_admin_cb_ctx *ctx = (struct salloc_stat_admin_cb_ctx *) cb_ctx;
-
-	tbuf_printf(ctx->out,
-		    "     - { item_size: %6i, slabs: %6i, items: %11" PRIi64
-		    ", bytes_used: %12" PRIi64 ", waste: %5.2f%%"
-		    ", bytes_free: %12" PRIi64 " }" CRLF,
-		    (int)cstat->item_size,
-		    (int)cstat->slabs,
-		    cstat->items,
-		    cstat->bytes_used,
-		    (double)(cstat->bytes_alloc_real - cstat->bytes_used_real)*100 /
-		    (cstat->bytes_alloc_real + 0.001),
-		    cstat->bytes_free);
-
-	ctx->total_used += cstat->bytes_used;
-	ctx->total_alloc_real += cstat->bytes_alloc_real;
-	ctx->total_used_real += cstat->bytes_used_real;
-	return 0;
-}
-
-static void
-show_slab(struct tbuf *out)
-{
-	struct salloc_stat_admin_cb_ctx cb_ctx;
-	struct slab_arena_stats astat;
-
-	cb_ctx.total_used = 0;
-	cb_ctx.total_used_real = 0;
-	cb_ctx.total_alloc_real = 0;
-	cb_ctx.out = out;
-
-	tbuf_printf(out, "slab statistics:\n  classes:" CRLF);
-
-	salloc_stat(salloc_stat_admin_cb, &astat, &cb_ctx);
-
-	tbuf_printf(out, "  items_used: %.2f%%" CRLF,
-		(double)cb_ctx.total_used / astat.size * 100);
-	tbuf_printf(out, "  arena_used: %.2f%%" CRLF,
-		(double)astat.used / astat.size * 100);
-	tbuf_printf(out, "  waste: %.2f%%" CRLF,
-		    (double)(cb_ctx.total_alloc_real - cb_ctx.total_used_real) / (cb_ctx.total_alloc_real + 0.001) * 100);
-	tbuf_printf(out, "  bytes_waste: %12" PRIi64 CRLF,
-		    (int64_t)((double)cb_ctx.total_used*(cb_ctx.total_alloc_real - cb_ctx.total_used_real) /
-			      (cb_ctx.total_alloc_real + 0.001)));
-}
-
-static void
-end(struct tbuf *out)
-{
-	tbuf_printf(out, "..." CRLF);
-}
-
-static void
-start(struct tbuf *out)
-{
-	tbuf_printf(out, "---" CRLF);
-}
-
-static void
-ok(struct tbuf *out)
-{
-	start(out);
-	tbuf_printf(out, "ok" CRLF);
-	end(out);
-}
-
-static void
-fail(struct tbuf *out, struct tbuf *err)
-{
-	start(out);
-	tbuf_printf(out, "fail:%.*s" CRLF, err->size, (char *)err->data);
-	end(out);
-}
-
-static void
-index_info(struct tbuf *out)
-{
-	tbuf_printf(out, "index:" CRLF);
-	struct space_stat *stat = space_stat();
-	int sp_i = 0;
-	int64_t total_size = 0;
-	while (stat[sp_i].n >= 0) {
-		tbuf_printf(out, "  - space: %" PRIi32 CRLF, stat[sp_i].n);
-		int64_t sp_size = 0;
-		int i;
-		for (i = 0; stat[sp_i].index[i].n >= 0; ++i)
-			sp_size += stat[sp_i].index[i].memsize;
-
-		tbuf_printf(out, "    memsize: %15" PRIi64 CRLF, sp_size);
-		total_size += sp_size;
-		tbuf_printf(out, "    index: " CRLF);
-		for (i = 0; stat[sp_i].index[i].n >= 0; ++i) {
-			tbuf_printf(out, "      - { n: %3d, keys: %15" PRIi64 ", memsize: %15" PRIi64 " }" CRLF,
-				    stat[sp_i].index[i].n, stat[sp_i].index[i].keys, stat[sp_i].index[i].memsize);
-		}
-		++sp_i;
-	}
-	tbuf_printf(out, "memsize:     %15" PRIi64 CRLF, total_size);
-}
-
-static void
-tarantool_info(struct tbuf *out)
-{
-	tbuf_printf(out, "info:" CRLF);
-	tbuf_printf(out, "  version: \"%s\"" CRLF, tarantool_version());
-	tbuf_printf(out, "  uptime: %i" CRLF, (int)tarantool_uptime());
-	tbuf_printf(out, "  pid: %i" CRLF, getpid());
-	tbuf_printf(out, "  logger_pid: %i" CRLF, logger_pid);
-	tbuf_printf(out, "  snapshot_pid: %i" CRLF, snapshot_pid);
-	tbuf_printf(out, "  lsn: %" PRIi64 CRLF,
-		    recovery_state->confirmed_lsn);
-	tbuf_printf(out, "  recovery_lag: %.3f" CRLF,
-		    recovery_state->remote ?
-		    recovery_state->remote->recovery_lag : 0);
-	tbuf_printf(out, "  recovery_last_update: %.3f" CRLF,
-		    recovery_state->remote ?
-		    recovery_state->remote->recovery_last_update_tstamp :0);
-	box_info(out);
-	const char *path = cfg_filename_fullpath;
-	if (path == NULL)
-		path = cfg_filename;
-	tbuf_printf(out, "  config: \"%s\"" CRLF, path);
-}
-
-static int
-show_stat_item(const char *name, int rps, int64_t total, void *ctx)
-{
-	struct tbuf *buf = (struct tbuf *) ctx;
-	int name_len = strlen(name);
-	tbuf_printf(buf,
-		    "  %s:%*s{ rps: %- 6i, total: %- 12" PRIi64 " }" CRLF,
-		    name, 1 + stat_max_name_len - name_len, " ", rps, total);
-	return 0;
-}
-
-void
-show_stat(struct tbuf *buf)
-{
-	tbuf_printf(buf, "statistics:" CRLF);
-	stat_foreach(show_stat_item, buf);
-}
-
-static int
-admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
-{
-	struct ibuf *in = &iobuf->in;
-	struct tbuf *out = tbuf_new(fiber_ptr->gc_pool);
-	struct tbuf *err = tbuf_new(fiber_ptr->gc_pool);
-	int cs;
-	char *p, *pe;
-	char *strstart, *strend;
-	bool state;
-
-	while ((pe = (char *) memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
-		if (coio_bread(coio, in, 1) <= 0)
-			return -1;
-	}
-
-	pe++;
-	p = in->pos;
-
-	
-#line 267 "src/admin.cc"
-	{
-	cs = admin_start;
-	}
-
-#line 272 "src/admin.cc"
-	{
-	if ( p == pe )
-		goto _test_eof;
-	switch ( cs )
-	{
-case 1:
-	switch( (*p) ) {
-		case 99: goto st2;
-		case 101: goto st13;
-		case 104: goto st17;
-		case 108: goto st21;
-		case 113: goto st27;
-		case 114: goto st28;
-		case 115: goto st48;
-	}
-	goto st0;
-st0:
-cs = 0;
-	goto _out;
-st2:
-	if ( ++p == pe )
-		goto _test_eof2;
-case 2:
-	if ( (*p) == 104 )
-		goto st3;
-	goto st0;
-st3:
-	if ( ++p == pe )
-		goto _test_eof3;
-case 3:
-	switch( (*p) ) {
-		case 32: goto st4;
-		case 101: goto st10;
-	}
-	goto st0;
-st4:
-	if ( ++p == pe )
-		goto _test_eof4;
-case 4:
-	switch( (*p) ) {
-		case 32: goto st4;
-		case 115: goto st5;
-	}
-	goto st0;
-st5:
-	if ( ++p == pe )
-		goto _test_eof5;
-case 5:
-	if ( (*p) == 108 )
-		goto st6;
-	goto st0;
-st6:
-	if ( ++p == pe )
-		goto _test_eof6;
-case 6:
-	switch( (*p) ) {
-		case 10: goto tr13;
-		case 13: goto tr14;
-		case 97: goto st8;
-	}
-	goto st0;
-tr13:
-#line 357 "src/admin.rl"
-	{slab_validate(); ok(out);}
-	goto st139;
-tr20:
-#line 344 "src/admin.rl"
-	{return -1;}
-	goto st139;
-tr25:
-#line 269 "src/admin.rl"
-	{
-			start(out);
-			tbuf_append(out, help, strlen(help));
-			end(out);
-		}
-	goto st139;
-tr36:
-#line 330 "src/admin.rl"
-	{strend = p;}
-#line 275 "src/admin.rl"
-	{
-			strstart[strend-strstart]='\0';
-			start(out);
-			tarantool_lua(L, out, strstart);
-			end(out);
-		}
-	goto st139;
-tr43:
-#line 282 "src/admin.rl"
-	{
-			if (reload_cfg(err))
-				fail(out, err);
-			else
-				ok(out);
-		}
-	goto st139;
-tr67:
-#line 355 "src/admin.rl"
-	{coredump(60); ok(out);}
-	goto st139;
-tr76:
-#line 289 "src/admin.rl"
-	{
-			int ret = snapshot();
-
-			if (ret == 0)
-				ok(out);
-			else {
-				tbuf_printf(err, " can't save snapshot, errno %d (%s)",
-					    ret, strerror(ret));
-
-				fail(out, err);
-			}
-		}
-	goto st139;
-tr98:
-#line 340 "src/admin.rl"
-	{ state = false; }
-#line 302 "src/admin.rl"
-	{
-			strstart[strend-strstart] = '\0';
-			if (errinj_set_byname(strstart, state)) {
-				tbuf_printf(err, "can't find error injection '%s'", strstart);
-				fail(out, err);
-			} else {
-				ok(out);
-			}
-		}
-	goto st139;
-tr101:
-#line 339 "src/admin.rl"
-	{ state = true; }
-#line 302 "src/admin.rl"
-	{
-			strstart[strend-strstart] = '\0';
-			if (errinj_set_byname(strstart, state)) {
-				tbuf_printf(err, "can't find error injection '%s'", strstart);
-				fail(out, err);
-			} else {
-				ok(out);
-			}
-		}
-	goto st139;
-tr117:
-#line 257 "src/admin.rl"
-	{
-			start(out);
-			show_cfg(out);
-			end(out);
-		}
-	goto st139;
-tr131:
-#line 348 "src/admin.rl"
-	{start(out); fiber_info(out); end(out);}
-	goto st139;
-tr139:
-#line 347 "src/admin.rl"
-	{start(out); index_info(out); end(out);}
-	goto st139;
-tr141:
-#line 346 "src/admin.rl"
-	{start(out); tarantool_info(out); end(out);}
-	goto st139;
-tr152:
-#line 263 "src/admin.rl"
-	{
-			start(out);
-			errinj_info(out);
-			end(out);
-		}
-	goto st139;
-tr158:
-#line 351 "src/admin.rl"
-	{start(out); palloc_stat(out); end(out);}
-	goto st139;
-tr166:
-#line 350 "src/admin.rl"
-	{start(out); show_slab(out); end(out);}
-	goto st139;
-tr170:
-#line 352 "src/admin.rl"
-	{start(out); show_stat(out);end(out);}
-	goto st139;
-st139:
-	if ( ++p == pe )
-		goto _test_eof139;
-case 139:
-#line 461 "src/admin.cc"
-	goto st0;
-tr14:
-#line 357 "src/admin.rl"
-	{slab_validate(); ok(out);}
-	goto st7;
-tr21:
-#line 344 "src/admin.rl"
-	{return -1;}
-	goto st7;
-tr26:
-#line 269 "src/admin.rl"
-	{
-			start(out);
-			tbuf_append(out, help, strlen(help));
-			end(out);
-		}
-	goto st7;
-tr37:
-#line 330 "src/admin.rl"
-	{strend = p;}
-#line 275 "src/admin.rl"
-	{
-			strstart[strend-strstart]='\0';
-			start(out);
-			tarantool_lua(L, out, strstart);
-			end(out);
-		}
-	goto st7;
-tr44:
-#line 282 "src/admin.rl"
-	{
-			if (reload_cfg(err))
-				fail(out, err);
-			else
-				ok(out);
-		}
-	goto st7;
-tr68:
-#line 355 "src/admin.rl"
-	{coredump(60); ok(out);}
-	goto st7;
-tr77:
-#line 289 "src/admin.rl"
-	{
-			int ret = snapshot();
-
-			if (ret == 0)
-				ok(out);
-			else {
-				tbuf_printf(err, " can't save snapshot, errno %d (%s)",
-					    ret, strerror(ret));
-
-				fail(out, err);
-			}
-		}
-	goto st7;
-tr99:
-#line 340 "src/admin.rl"
-	{ state = false; }
-#line 302 "src/admin.rl"
-	{
-			strstart[strend-strstart] = '\0';
-			if (errinj_set_byname(strstart, state)) {
-				tbuf_printf(err, "can't find error injection '%s'", strstart);
-				fail(out, err);
-			} else {
-				ok(out);
-			}
-		}
-	goto st7;
-tr102:
-#line 339 "src/admin.rl"
-	{ state = true; }
-#line 302 "src/admin.rl"
-	{
-			strstart[strend-strstart] = '\0';
-			if (errinj_set_byname(strstart, state)) {
-				tbuf_printf(err, "can't find error injection '%s'", strstart);
-				fail(out, err);
-			} else {
-				ok(out);
-			}
-		}
-	goto st7;
-tr118:
-#line 257 "src/admin.rl"
-	{
-			start(out);
-			show_cfg(out);
-			end(out);
-		}
-	goto st7;
-tr132:
-#line 348 "src/admin.rl"
-	{start(out); fiber_info(out); end(out);}
-	goto st7;
-tr140:
-#line 347 "src/admin.rl"
-	{start(out); index_info(out); end(out);}
-	goto st7;
-tr142:
-#line 346 "src/admin.rl"
-	{start(out); tarantool_info(out); end(out);}
-	goto st7;
-tr153:
-#line 263 "src/admin.rl"
-	{
-			start(out);
-			errinj_info(out);
-			end(out);
-		}
-	goto st7;
-tr159:
-#line 351 "src/admin.rl"
-	{start(out); palloc_stat(out); end(out);}
-	goto st7;
-tr167:
-#line 350 "src/admin.rl"
-	{start(out); show_slab(out); end(out);}
-	goto st7;
-tr171:
-#line 352 "src/admin.rl"
-	{start(out); show_stat(out);end(out);}
-	goto st7;
-st7:
-	if ( ++p == pe )
-		goto _test_eof7;
-case 7:
-#line 590 "src/admin.cc"
-	if ( (*p) == 10 )
-		goto st139;
-	goto st0;
-st8:
-	if ( ++p == pe )
-		goto _test_eof8;
-case 8:
-	switch( (*p) ) {
-		case 10: goto tr13;
-		case 13: goto tr14;
-		case 98: goto st9;
-	}
-	goto st0;
-st9:
-	if ( ++p == pe )
-		goto _test_eof9;
-case 9:
-	switch( (*p) ) {
-		case 10: goto tr13;
-		case 13: goto tr14;
-	}
-	goto st0;
-st10:
-	if ( ++p == pe )
-		goto _test_eof10;
-case 10:
-	switch( (*p) ) {
-		case 32: goto st4;
-		case 99: goto st11;
-	}
-	goto st0;
-st11:
-	if ( ++p == pe )
-		goto _test_eof11;
-case 11:
-	switch( (*p) ) {
-		case 32: goto st4;
-		case 107: goto st12;
-	}
-	goto st0;
-st12:
-	if ( ++p == pe )
-		goto _test_eof12;
-case 12:
-	if ( (*p) == 32 )
-		goto st4;
-	goto st0;
-st13:
-	if ( ++p == pe )
-		goto _test_eof13;
-case 13:
-	switch( (*p) ) {
-		case 10: goto tr20;
-		case 13: goto tr21;
-		case 120: goto st14;
-	}
-	goto st0;
-st14:
-	if ( ++p == pe )
-		goto _test_eof14;
-case 14:
-	switch( (*p) ) {
-		case 10: goto tr20;
-		case 13: goto tr21;
-		case 105: goto st15;
-	}
-	goto st0;
-st15:
-	if ( ++p == pe )
-		goto _test_eof15;
-case 15:
-	switch( (*p) ) {
-		case 10: goto tr20;
-		case 13: goto tr21;
-		case 116: goto st16;
-	}
-	goto st0;
-st16:
-	if ( ++p == pe )
-		goto _test_eof16;
-case 16:
-	switch( (*p) ) {
-		case 10: goto tr20;
-		case 13: goto tr21;
-	}
-	goto st0;
-st17:
-	if ( ++p == pe )
-		goto _test_eof17;
-case 17:
-	switch( (*p) ) {
-		case 10: goto tr25;
-		case 13: goto tr26;
-		case 101: goto st18;
-	}
-	goto st0;
-st18:
-	if ( ++p == pe )
-		goto _test_eof18;
-case 18:
-	switch( (*p) ) {
-		case 10: goto tr25;
-		case 13: goto tr26;
-		case 108: goto st19;
-	}
-	goto st0;
-st19:
-	if ( ++p == pe )
-		goto _test_eof19;
-case 19:
-	switch( (*p) ) {
-		case 10: goto tr25;
-		case 13: goto tr26;
-		case 112: goto st20;
-	}
-	goto st0;
-st20:
-	if ( ++p == pe )
-		goto _test_eof20;
-case 20:
-	switch( (*p) ) {
-		case 10: goto tr25;
-		case 13: goto tr26;
-	}
-	goto st0;
-st21:
-	if ( ++p == pe )
-		goto _test_eof21;
-case 21:
-	if ( (*p) == 117 )
-		goto st22;
-	goto st0;
-st22:
-	if ( ++p == pe )
-		goto _test_eof22;
-case 22:
-	switch( (*p) ) {
-		case 32: goto st23;
-		case 97: goto st26;
-	}
-	goto st0;
-st23:
-	if ( ++p == pe )
-		goto _test_eof23;
-case 23:
-	switch( (*p) ) {
-		case 10: goto st0;
-		case 13: goto st0;
-		case 32: goto tr34;
-	}
-	goto tr33;
-tr33:
-#line 330 "src/admin.rl"
-	{strstart = p;}
-	goto st24;
-st24:
-	if ( ++p == pe )
-		goto _test_eof24;
-case 24:
-#line 750 "src/admin.cc"
-	switch( (*p) ) {
-		case 10: goto tr36;
-		case 13: goto tr37;
-	}
-	goto st24;
-tr34:
-#line 330 "src/admin.rl"
-	{strstart = p;}
-	goto st25;
-st25:
-	if ( ++p == pe )
-		goto _test_eof25;
-case 25:
-#line 764 "src/admin.cc"
-	switch( (*p) ) {
-		case 10: goto tr36;
-		case 13: goto tr37;
-		case 32: goto tr34;
-	}
-	goto tr33;
-st26:
-	if ( ++p == pe )
-		goto _test_eof26;
-case 26:
-	if ( (*p) == 32 )
-		goto st23;
-	goto st0;
-st27:
-	if ( ++p == pe )
-		goto _test_eof27;
-case 27:
-	switch( (*p) ) {
-		case 10: goto tr20;
-		case 13: goto tr21;
-		case 117: goto st14;
-	}
-	goto st0;
-st28:
-	if ( ++p == pe )
-		goto _test_eof28;
-case 28:
-	if ( (*p) == 101 )
-		goto st29;
-	goto st0;
-st29:
-	if ( ++p == pe )
-		goto _test_eof29;
-case 29:
-	switch( (*p) ) {
-		case 32: goto st30;
-		case 108: goto st44;
-	}
-	goto st0;
-st30:
-	if ( ++p == pe )
-		goto _test_eof30;
-case 30:
-	switch( (*p) ) {
-		case 32: goto st30;
-		case 99: goto st31;
-	}
-	goto st0;
-st31:
-	if ( ++p == pe )
-		goto _test_eof31;
-case 31:
-	if ( (*p) == 111 )
-		goto st32;
-	goto st0;
-st32:
-	if ( ++p == pe )
-		goto _test_eof32;
-case 32:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 110: goto st33;
-	}
-	goto st0;
-st33:
-	if ( ++p == pe )
-		goto _test_eof33;
-case 33:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 102: goto st34;
-	}
-	goto st0;
-st34:
-	if ( ++p == pe )
-		goto _test_eof34;
-case 34:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 105: goto st35;
-	}
-	goto st0;
-st35:
-	if ( ++p == pe )
-		goto _test_eof35;
-case 35:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 103: goto st36;
-	}
-	goto st0;
-st36:
-	if ( ++p == pe )
-		goto _test_eof36;
-case 36:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 117: goto st37;
-	}
-	goto st0;
-st37:
-	if ( ++p == pe )
-		goto _test_eof37;
-case 37:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 114: goto st38;
-	}
-	goto st0;
-st38:
-	if ( ++p == pe )
-		goto _test_eof38;
-case 38:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 97: goto st39;
-	}
-	goto st0;
-st39:
-	if ( ++p == pe )
-		goto _test_eof39;
-case 39:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 116: goto st40;
-	}
-	goto st0;
-st40:
-	if ( ++p == pe )
-		goto _test_eof40;
-case 40:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 105: goto st41;
-	}
-	goto st0;
-st41:
-	if ( ++p == pe )
-		goto _test_eof41;
-case 41:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 111: goto st42;
-	}
-	goto st0;
-st42:
-	if ( ++p == pe )
-		goto _test_eof42;
-case 42:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-		case 110: goto st43;
-	}
-	goto st0;
-st43:
-	if ( ++p == pe )
-		goto _test_eof43;
-case 43:
-	switch( (*p) ) {
-		case 10: goto tr43;
-		case 13: goto tr44;
-	}
-	goto st0;
-st44:
-	if ( ++p == pe )
-		goto _test_eof44;
-case 44:
-	switch( (*p) ) {
-		case 32: goto st30;
-		case 111: goto st45;
-	}
-	goto st0;
-st45:
-	if ( ++p == pe )
-		goto _test_eof45;
-case 45:
-	switch( (*p) ) {
-		case 32: goto st30;
-		case 97: goto st46;
-	}
-	goto st0;
-st46:
-	if ( ++p == pe )
-		goto _test_eof46;
-case 46:
-	switch( (*p) ) {
-		case 32: goto st30;
-		case 100: goto st47;
-	}
-	goto st0;
-st47:
-	if ( ++p == pe )
-		goto _test_eof47;
-case 47:
-	if ( (*p) == 32 )
-		goto st30;
-	goto st0;
-st48:
-	if ( ++p == pe )
-		goto _test_eof48;
-case 48:
-	switch( (*p) ) {
-		case 97: goto st49;
-		case 101: goto st69;
-		case 104: goto st88;
-	}
-	goto st0;
-st49:
-	if ( ++p == pe )
-		goto _test_eof49;
-case 49:
-	switch( (*p) ) {
-		case 32: goto st50;
-		case 118: goto st67;
-	}
-	goto st0;
-st50:
-	if ( ++p == pe )
-		goto _test_eof50;
-case 50:
-	switch( (*p) ) {
-		case 32: goto st50;
-		case 99: goto st51;
-		case 115: goto st59;
-	}
-	goto st0;
-st51:
-	if ( ++p == pe )
-		goto _test_eof51;
-case 51:
-	if ( (*p) == 111 )
-		goto st52;
-	goto st0;
-st52:
-	if ( ++p == pe )
-		goto _test_eof52;
-case 52:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 114: goto st53;
-	}
-	goto st0;
-st53:
-	if ( ++p == pe )
-		goto _test_eof53;
-case 53:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 101: goto st54;
-	}
-	goto st0;
-st54:
-	if ( ++p == pe )
-		goto _test_eof54;
-case 54:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 100: goto st55;
-	}
-	goto st0;
-st55:
-	if ( ++p == pe )
-		goto _test_eof55;
-case 55:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 117: goto st56;
-	}
-	goto st0;
-st56:
-	if ( ++p == pe )
-		goto _test_eof56;
-case 56:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 109: goto st57;
-	}
-	goto st0;
-st57:
-	if ( ++p == pe )
-		goto _test_eof57;
-case 57:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-		case 112: goto st58;
-	}
-	goto st0;
-st58:
-	if ( ++p == pe )
-		goto _test_eof58;
-case 58:
-	switch( (*p) ) {
-		case 10: goto tr67;
-		case 13: goto tr68;
-	}
-	goto st0;
-st59:
-	if ( ++p == pe )
-		goto _test_eof59;
-case 59:
-	if ( (*p) == 110 )
-		goto st60;
-	goto st0;
-st60:
-	if ( ++p == pe )
-		goto _test_eof60;
-case 60:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 97: goto st61;
-	}
-	goto st0;
-st61:
-	if ( ++p == pe )
-		goto _test_eof61;
-case 61:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 112: goto st62;
-	}
-	goto st0;
-st62:
-	if ( ++p == pe )
-		goto _test_eof62;
-case 62:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 115: goto st63;
-	}
-	goto st0;
-st63:
-	if ( ++p == pe )
-		goto _test_eof63;
-case 63:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 104: goto st64;
-	}
-	goto st0;
-st64:
-	if ( ++p == pe )
-		goto _test_eof64;
-case 64:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 111: goto st65;
-	}
-	goto st0;
-st65:
-	if ( ++p == pe )
-		goto _test_eof65;
-case 65:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-		case 116: goto st66;
-	}
-	goto st0;
-st66:
-	if ( ++p == pe )
-		goto _test_eof66;
-case 66:
-	switch( (*p) ) {
-		case 10: goto tr76;
-		case 13: goto tr77;
-	}
-	goto st0;
-st67:
-	if ( ++p == pe )
-		goto _test_eof67;
-case 67:
-	switch( (*p) ) {
-		case 32: goto st50;
-		case 101: goto st68;
-	}
-	goto st0;
-st68:
-	if ( ++p == pe )
-		goto _test_eof68;
-case 68:
-	if ( (*p) == 32 )
-		goto st50;
-	goto st0;
-st69:
-	if ( ++p == pe )
-		goto _test_eof69;
-case 69:
-	switch( (*p) ) {
-		case 32: goto st70;
-		case 116: goto st87;
-	}
-	goto st0;
-st70:
-	if ( ++p == pe )
-		goto _test_eof70;
-case 70:
-	switch( (*p) ) {
-		case 32: goto st70;
-		case 105: goto st71;
-	}
-	goto st0;
-st71:
-	if ( ++p == pe )
-		goto _test_eof71;
-case 71:
-	if ( (*p) == 110 )
-		goto st72;
-	goto st0;
-st72:
-	if ( ++p == pe )
-		goto _test_eof72;
-case 72:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 106: goto st80;
-	}
-	goto st0;
-st73:
-	if ( ++p == pe )
-		goto _test_eof73;
-case 73:
-	if ( (*p) == 32 )
-		goto st73;
-	if ( 33 <= (*p) && (*p) <= 126 )
-		goto tr91;
-	goto st0;
-tr91:
-#line 338 "src/admin.rl"
-	{ strstart = p; }
-	goto st74;
-st74:
-	if ( ++p == pe )
-		goto _test_eof74;
-case 74:
-#line 1221 "src/admin.cc"
-	if ( (*p) == 32 )
-		goto tr92;
-	if ( 33 <= (*p) && (*p) <= 126 )
-		goto st74;
-	goto st0;
-tr92:
-#line 338 "src/admin.rl"
-	{ strend = p; }
-	goto st75;
-st75:
-	if ( ++p == pe )
-		goto _test_eof75;
-case 75:
-#line 1235 "src/admin.cc"
-	switch( (*p) ) {
-		case 32: goto st75;
-		case 111: goto st76;
-	}
-	goto st0;
-st76:
-	if ( ++p == pe )
-		goto _test_eof76;
-case 76:
-	switch( (*p) ) {
-		case 102: goto st77;
-		case 110: goto st79;
-	}
-	goto st0;
-st77:
-	if ( ++p == pe )
-		goto _test_eof77;
-case 77:
-	switch( (*p) ) {
-		case 10: goto tr98;
-		case 13: goto tr99;
-		case 102: goto st78;
-	}
-	goto st0;
-st78:
-	if ( ++p == pe )
-		goto _test_eof78;
-case 78:
-	switch( (*p) ) {
-		case 10: goto tr98;
-		case 13: goto tr99;
-	}
-	goto st0;
-st79:
-	if ( ++p == pe )
-		goto _test_eof79;
-case 79:
-	switch( (*p) ) {
-		case 10: goto tr101;
-		case 13: goto tr102;
-	}
-	goto st0;
-st80:
-	if ( ++p == pe )
-		goto _test_eof80;
-case 80:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 101: goto st81;
-	}
-	goto st0;
-st81:
-	if ( ++p == pe )
-		goto _test_eof81;
-case 81:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 99: goto st82;
-	}
-	goto st0;
-st82:
-	if ( ++p == pe )
-		goto _test_eof82;
-case 82:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 116: goto st83;
-	}
-	goto st0;
-st83:
-	if ( ++p == pe )
-		goto _test_eof83;
-case 83:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 105: goto st84;
-	}
-	goto st0;
-st84:
-	if ( ++p == pe )
-		goto _test_eof84;
-case 84:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 111: goto st85;
-	}
-	goto st0;
-st85:
-	if ( ++p == pe )
-		goto _test_eof85;
-case 85:
-	switch( (*p) ) {
-		case 32: goto st73;
-		case 110: goto st86;
-	}
-	goto st0;
-st86:
-	if ( ++p == pe )
-		goto _test_eof86;
-case 86:
-	if ( (*p) == 32 )
-		goto st73;
-	goto st0;
-st87:
-	if ( ++p == pe )
-		goto _test_eof87;
-case 87:
-	if ( (*p) == 32 )
-		goto st70;
-	goto st0;
-st88:
-	if ( ++p == pe )
-		goto _test_eof88;
-case 88:
-	switch( (*p) ) {
-		case 32: goto st89;
-		case 111: goto st137;
-	}
-	goto st0;
-st89:
-	if ( ++p == pe )
-		goto _test_eof89;
-case 89:
-	switch( (*p) ) {
-		case 32: goto st89;
-		case 99: goto st90;
-		case 102: goto st103;
-		case 105: goto st108;
-		case 112: goto st124;
-		case 115: goto st130;
-	}
-	goto st0;
-st90:
-	if ( ++p == pe )
-		goto _test_eof90;
-case 90:
-	if ( (*p) == 111 )
-		goto st91;
-	goto st0;
-st91:
-	if ( ++p == pe )
-		goto _test_eof91;
-case 91:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 110: goto st92;
-	}
-	goto st0;
-st92:
-	if ( ++p == pe )
-		goto _test_eof92;
-case 92:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 102: goto st93;
-	}
-	goto st0;
-st93:
-	if ( ++p == pe )
-		goto _test_eof93;
-case 93:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 105: goto st94;
-	}
-	goto st0;
-st94:
-	if ( ++p == pe )
-		goto _test_eof94;
-case 94:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 103: goto st95;
-	}
-	goto st0;
-st95:
-	if ( ++p == pe )
-		goto _test_eof95;
-case 95:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 117: goto st96;
-	}
-	goto st0;
-st96:
-	if ( ++p == pe )
-		goto _test_eof96;
-case 96:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 114: goto st97;
-	}
-	goto st0;
-st97:
-	if ( ++p == pe )
-		goto _test_eof97;
-case 97:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 97: goto st98;
-	}
-	goto st0;
-st98:
-	if ( ++p == pe )
-		goto _test_eof98;
-case 98:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 116: goto st99;
-	}
-	goto st0;
-st99:
-	if ( ++p == pe )
-		goto _test_eof99;
-case 99:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 105: goto st100;
-	}
-	goto st0;
-st100:
-	if ( ++p == pe )
-		goto _test_eof100;
-case 100:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 111: goto st101;
-	}
-	goto st0;
-st101:
-	if ( ++p == pe )
-		goto _test_eof101;
-case 101:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-		case 110: goto st102;
-	}
-	goto st0;
-st102:
-	if ( ++p == pe )
-		goto _test_eof102;
-case 102:
-	switch( (*p) ) {
-		case 10: goto tr117;
-		case 13: goto tr118;
-	}
-	goto st0;
-st103:
-	if ( ++p == pe )
-		goto _test_eof103;
-case 103:
-	if ( (*p) == 105 )
-		goto st104;
-	goto st0;
-st104:
-	if ( ++p == pe )
-		goto _test_eof104;
-case 104:
-	switch( (*p) ) {
-		case 10: goto tr131;
-		case 13: goto tr132;
-		case 98: goto st105;
-	}
-	goto st0;
-st105:
-	if ( ++p == pe )
-		goto _test_eof105;
-case 105:
-	switch( (*p) ) {
-		case 10: goto tr131;
-		case 13: goto tr132;
-		case 101: goto st106;
-	}
-	goto st0;
-st106:
-	if ( ++p == pe )
-		goto _test_eof106;
-case 106:
-	switch( (*p) ) {
-		case 10: goto tr131;
-		case 13: goto tr132;
-		case 114: goto st107;
-	}
-	goto st0;
-st107:
-	if ( ++p == pe )
-		goto _test_eof107;
-case 107:
-	switch( (*p) ) {
-		case 10: goto tr131;
-		case 13: goto tr132;
-	}
-	goto st0;
-st108:
-	if ( ++p == pe )
-		goto _test_eof108;
-case 108:
-	switch( (*p) ) {
-		case 100: goto st109;
-		case 110: goto st111;
-	}
-	goto st0;
-st109:
-	if ( ++p == pe )
-		goto _test_eof109;
-case 109:
-	if ( (*p) == 120 )
-		goto st110;
-	goto st0;
-st110:
-	if ( ++p == pe )
-		goto _test_eof110;
-case 110:
-	switch( (*p) ) {
-		case 10: goto tr139;
-		case 13: goto tr140;
-	}
-	goto st0;
-st111:
-	if ( ++p == pe )
-		goto _test_eof111;
-case 111:
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto tr142;
-		case 100: goto st112;
-		case 102: goto st114;
-		case 106: goto st116;
-		case 115: goto st119;
-	}
-	goto st0;
-st112:
-	if ( ++p == pe )
-		goto _test_eof112;
-case 112:
-	switch( (*p) ) {
-		case 10: goto tr139;
-		case 13: goto tr140;
-		case 101: goto st113;
-	}
-	goto st0;
-st113:
-	if ( ++p == pe )
-		goto _test_eof113;
-case 113:
-	switch( (*p) ) {
-		case 10: goto tr139;
-		case 13: goto tr140;
-		case 120: goto st110;
-	}
-	goto st0;
-st114:
-	if ( ++p == pe )
-		goto _test_eof114;
-case 114:
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto tr142;
-		case 111: goto st115;
-	}
-	goto st0;
-st115:
-	if ( ++p == pe )
-		goto _test_eof115;
-case 115:
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto tr142;
-	}
-	goto st0;
-st116:
-	if ( ++p == pe )
-		goto _test_eof116;
-case 116:
-	switch( (*p) ) {
-		case 101: goto st117;
-		case 115: goto st119;
-	}
-	goto st0;
-st117:
-	if ( ++p == pe )
-		goto _test_eof117;
-case 117:
-	switch( (*p) ) {
-		case 99: goto st118;
-		case 115: goto st119;
-	}
-	goto st0;
-st118:
-	if ( ++p == pe )
-		goto _test_eof118;
-case 118:
-	switch( (*p) ) {
-		case 115: goto st119;
-		case 116: goto st120;
-	}
-	goto st0;
-st119:
-	if ( ++p == pe )
-		goto _test_eof119;
-case 119:
-	switch( (*p) ) {
-		case 10: goto tr152;
-		case 13: goto tr153;
-	}
-	goto st0;
-st120:
-	if ( ++p == pe )
-		goto _test_eof120;
-case 120:
-	switch( (*p) ) {
-		case 105: goto st121;
-		case 115: goto st119;
-	}
-	goto st0;
-st121:
-	if ( ++p == pe )
-		goto _test_eof121;
-case 121:
-	switch( (*p) ) {
-		case 111: goto st122;
-		case 115: goto st119;
-	}
-	goto st0;
-st122:
-	if ( ++p == pe )
-		goto _test_eof122;
-case 122:
-	switch( (*p) ) {
-		case 110: goto st123;
-		case 115: goto st119;
-	}
-	goto st0;
-st123:
-	if ( ++p == pe )
-		goto _test_eof123;
-case 123:
-	if ( (*p) == 115 )
-		goto st119;
-	goto st0;
-st124:
-	if ( ++p == pe )
-		goto _test_eof124;
-case 124:
-	if ( (*p) == 97 )
-		goto st125;
-	goto st0;
-st125:
-	if ( ++p == pe )
-		goto _test_eof125;
-case 125:
-	switch( (*p) ) {
-		case 10: goto tr158;
-		case 13: goto tr159;
-		case 108: goto st126;
-	}
-	goto st0;
-st126:
-	if ( ++p == pe )
-		goto _test_eof126;
-case 126:
-	switch( (*p) ) {
-		case 10: goto tr158;
-		case 13: goto tr159;
-		case 108: goto st127;
-	}
-	goto st0;
-st127:
-	if ( ++p == pe )
-		goto _test_eof127;
-case 127:
-	switch( (*p) ) {
-		case 10: goto tr158;
-		case 13: goto tr159;
-		case 111: goto st128;
-	}
-	goto st0;
-st128:
-	if ( ++p == pe )
-		goto _test_eof128;
-case 128:
-	switch( (*p) ) {
-		case 10: goto tr158;
-		case 13: goto tr159;
-		case 99: goto st129;
-	}
-	goto st0;
-st129:
-	if ( ++p == pe )
-		goto _test_eof129;
-case 129:
-	switch( (*p) ) {
-		case 10: goto tr158;
-		case 13: goto tr159;
-	}
-	goto st0;
-st130:
-	if ( ++p == pe )
-		goto _test_eof130;
-case 130:
-	switch( (*p) ) {
-		case 108: goto st131;
-		case 116: goto st134;
-	}
-	goto st0;
-st131:
-	if ( ++p == pe )
-		goto _test_eof131;
-case 131:
-	switch( (*p) ) {
-		case 10: goto tr166;
-		case 13: goto tr167;
-		case 97: goto st132;
-	}
-	goto st0;
-st132:
-	if ( ++p == pe )
-		goto _test_eof132;
-case 132:
-	switch( (*p) ) {
-		case 10: goto tr166;
-		case 13: goto tr167;
-		case 98: goto st133;
-	}
-	goto st0;
-st133:
-	if ( ++p == pe )
-		goto _test_eof133;
-case 133:
-	switch( (*p) ) {
-		case 10: goto tr166;
-		case 13: goto tr167;
-	}
-	goto st0;
-st134:
-	if ( ++p == pe )
-		goto _test_eof134;
-case 134:
-	switch( (*p) ) {
-		case 10: goto tr170;
-		case 13: goto tr171;
-		case 97: goto st135;
-	}
-	goto st0;
-st135:
-	if ( ++p == pe )
-		goto _test_eof135;
-case 135:
-	switch( (*p) ) {
-		case 10: goto tr170;
-		case 13: goto tr171;
-		case 116: goto st136;
-	}
-	goto st0;
-st136:
-	if ( ++p == pe )
-		goto _test_eof136;
-case 136:
-	switch( (*p) ) {
-		case 10: goto tr170;
-		case 13: goto tr171;
-	}
-	goto st0;
-st137:
-	if ( ++p == pe )
-		goto _test_eof137;
-case 137:
-	switch( (*p) ) {
-		case 32: goto st89;
-		case 119: goto st138;
-	}
-	goto st0;
-st138:
-	if ( ++p == pe )
-		goto _test_eof138;
-case 138:
-	if ( (*p) == 32 )
-		goto st89;
-	goto st0;
-	}
-	_test_eof2: cs = 2; goto _test_eof; 
-	_test_eof3: cs = 3; goto _test_eof; 
-	_test_eof4: cs = 4; goto _test_eof; 
-	_test_eof5: cs = 5; goto _test_eof; 
-	_test_eof6: cs = 6; goto _test_eof; 
-	_test_eof139: cs = 139; goto _test_eof; 
-	_test_eof7: cs = 7; goto _test_eof; 
-	_test_eof8: cs = 8; goto _test_eof; 
-	_test_eof9: cs = 9; goto _test_eof; 
-	_test_eof10: cs = 10; goto _test_eof; 
-	_test_eof11: cs = 11; goto _test_eof; 
-	_test_eof12: cs = 12; goto _test_eof; 
-	_test_eof13: cs = 13; goto _test_eof; 
-	_test_eof14: cs = 14; goto _test_eof; 
-	_test_eof15: cs = 15; goto _test_eof; 
-	_test_eof16: cs = 16; goto _test_eof; 
-	_test_eof17: cs = 17; goto _test_eof; 
-	_test_eof18: cs = 18; goto _test_eof; 
-	_test_eof19: cs = 19; goto _test_eof; 
-	_test_eof20: cs = 20; goto _test_eof; 
-	_test_eof21: cs = 21; goto _test_eof; 
-	_test_eof22: cs = 22; goto _test_eof; 
-	_test_eof23: cs = 23; goto _test_eof; 
-	_test_eof24: cs = 24; goto _test_eof; 
-	_test_eof25: cs = 25; goto _test_eof; 
-	_test_eof26: cs = 26; goto _test_eof; 
-	_test_eof27: cs = 27; goto _test_eof; 
-	_test_eof28: cs = 28; goto _test_eof; 
-	_test_eof29: cs = 29; goto _test_eof; 
-	_test_eof30: cs = 30; goto _test_eof; 
-	_test_eof31: cs = 31; goto _test_eof; 
-	_test_eof32: cs = 32; goto _test_eof; 
-	_test_eof33: cs = 33; goto _test_eof; 
-	_test_eof34: cs = 34; goto _test_eof; 
-	_test_eof35: cs = 35; goto _test_eof; 
-	_test_eof36: cs = 36; goto _test_eof; 
-	_test_eof37: cs = 37; goto _test_eof; 
-	_test_eof38: cs = 38; goto _test_eof; 
-	_test_eof39: cs = 39; goto _test_eof; 
-	_test_eof40: cs = 40; goto _test_eof; 
-	_test_eof41: cs = 41; goto _test_eof; 
-	_test_eof42: cs = 42; goto _test_eof; 
-	_test_eof43: cs = 43; goto _test_eof; 
-	_test_eof44: cs = 44; goto _test_eof; 
-	_test_eof45: cs = 45; goto _test_eof; 
-	_test_eof46: cs = 46; goto _test_eof; 
-	_test_eof47: cs = 47; goto _test_eof; 
-	_test_eof48: cs = 48; goto _test_eof; 
-	_test_eof49: cs = 49; goto _test_eof; 
-	_test_eof50: cs = 50; goto _test_eof; 
-	_test_eof51: cs = 51; goto _test_eof; 
-	_test_eof52: cs = 52; goto _test_eof; 
-	_test_eof53: cs = 53; goto _test_eof; 
-	_test_eof54: cs = 54; goto _test_eof; 
-	_test_eof55: cs = 55; goto _test_eof; 
-	_test_eof56: cs = 56; goto _test_eof; 
-	_test_eof57: cs = 57; goto _test_eof; 
-	_test_eof58: cs = 58; goto _test_eof; 
-	_test_eof59: cs = 59; goto _test_eof; 
-	_test_eof60: cs = 60; goto _test_eof; 
-	_test_eof61: cs = 61; goto _test_eof; 
-	_test_eof62: cs = 62; goto _test_eof; 
-	_test_eof63: cs = 63; goto _test_eof; 
-	_test_eof64: cs = 64; goto _test_eof; 
-	_test_eof65: cs = 65; goto _test_eof; 
-	_test_eof66: cs = 66; goto _test_eof; 
-	_test_eof67: cs = 67; goto _test_eof; 
-	_test_eof68: cs = 68; goto _test_eof; 
-	_test_eof69: cs = 69; goto _test_eof; 
-	_test_eof70: cs = 70; goto _test_eof; 
-	_test_eof71: cs = 71; goto _test_eof; 
-	_test_eof72: cs = 72; goto _test_eof; 
-	_test_eof73: cs = 73; goto _test_eof; 
-	_test_eof74: cs = 74; goto _test_eof; 
-	_test_eof75: cs = 75; goto _test_eof; 
-	_test_eof76: cs = 76; goto _test_eof; 
-	_test_eof77: cs = 77; goto _test_eof; 
-	_test_eof78: cs = 78; goto _test_eof; 
-	_test_eof79: cs = 79; goto _test_eof; 
-	_test_eof80: cs = 80; goto _test_eof; 
-	_test_eof81: cs = 81; goto _test_eof; 
-	_test_eof82: cs = 82; goto _test_eof; 
-	_test_eof83: cs = 83; goto _test_eof; 
-	_test_eof84: cs = 84; goto _test_eof; 
-	_test_eof85: cs = 85; goto _test_eof; 
-	_test_eof86: cs = 86; goto _test_eof; 
-	_test_eof87: cs = 87; goto _test_eof; 
-	_test_eof88: cs = 88; goto _test_eof; 
-	_test_eof89: cs = 89; goto _test_eof; 
-	_test_eof90: cs = 90; goto _test_eof; 
-	_test_eof91: cs = 91; goto _test_eof; 
-	_test_eof92: cs = 92; goto _test_eof; 
-	_test_eof93: cs = 93; goto _test_eof; 
-	_test_eof94: cs = 94; goto _test_eof; 
-	_test_eof95: cs = 95; goto _test_eof; 
-	_test_eof96: cs = 96; goto _test_eof; 
-	_test_eof97: cs = 97; goto _test_eof; 
-	_test_eof98: cs = 98; goto _test_eof; 
-	_test_eof99: cs = 99; goto _test_eof; 
-	_test_eof100: cs = 100; goto _test_eof; 
-	_test_eof101: cs = 101; goto _test_eof; 
-	_test_eof102: cs = 102; goto _test_eof; 
-	_test_eof103: cs = 103; goto _test_eof; 
-	_test_eof104: cs = 104; goto _test_eof; 
-	_test_eof105: cs = 105; goto _test_eof; 
-	_test_eof106: cs = 106; goto _test_eof; 
-	_test_eof107: cs = 107; goto _test_eof; 
-	_test_eof108: cs = 108; goto _test_eof; 
-	_test_eof109: cs = 109; goto _test_eof; 
-	_test_eof110: cs = 110; goto _test_eof; 
-	_test_eof111: cs = 111; goto _test_eof; 
-	_test_eof112: cs = 112; goto _test_eof; 
-	_test_eof113: cs = 113; goto _test_eof; 
-	_test_eof114: cs = 114; goto _test_eof; 
-	_test_eof115: cs = 115; goto _test_eof; 
-	_test_eof116: cs = 116; goto _test_eof; 
-	_test_eof117: cs = 117; goto _test_eof; 
-	_test_eof118: cs = 118; goto _test_eof; 
-	_test_eof119: cs = 119; goto _test_eof; 
-	_test_eof120: cs = 120; goto _test_eof; 
-	_test_eof121: cs = 121; goto _test_eof; 
-	_test_eof122: cs = 122; goto _test_eof; 
-	_test_eof123: cs = 123; goto _test_eof; 
-	_test_eof124: cs = 124; goto _test_eof; 
-	_test_eof125: cs = 125; goto _test_eof; 
-	_test_eof126: cs = 126; goto _test_eof; 
-	_test_eof127: cs = 127; goto _test_eof; 
-	_test_eof128: cs = 128; goto _test_eof; 
-	_test_eof129: cs = 129; goto _test_eof; 
-	_test_eof130: cs = 130; goto _test_eof; 
-	_test_eof131: cs = 131; goto _test_eof; 
-	_test_eof132: cs = 132; goto _test_eof; 
-	_test_eof133: cs = 133; goto _test_eof; 
-	_test_eof134: cs = 134; goto _test_eof; 
-	_test_eof135: cs = 135; goto _test_eof; 
-	_test_eof136: cs = 136; goto _test_eof; 
-	_test_eof137: cs = 137; goto _test_eof; 
-	_test_eof138: cs = 138; goto _test_eof; 
-
-	_test_eof: {}
-	_out: {}
-	}
-
-#line 363 "src/admin.rl"
-
-
-	in->pos = pe;
-
-	if (p != pe) {
-		start(out);
-		tbuf_append(out, unknown_command, strlen(unknown_command));
-		end(out);
-	}
-
-	coio_write(coio, out->data, out->size);
-	return 0;
-}
-
-static void
-admin_handler(va_list ap)
-{
-	struct ev_io coio = va_arg(ap, struct ev_io);
-	struct sockaddr_in *addr = va_arg(ap, struct sockaddr_in *);
-	struct iobuf *iobuf = va_arg(ap, struct iobuf *);
-	lua_State *L = lua_newthread(tarantool_L);
-	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
-
-	auto scoped_guard = make_scoped_guard([&] {
-		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
-		evio_close(&coio);
-		iobuf_delete(iobuf);
-		session_destroy(fiber_ptr->sid);
-	});
-
-	/*
-	 * Admin and iproto connections must have a
-	 * session object, representing the state of
-	 * a remote client: it's used in Lua
-	 * stored procedures.
-	 */
-	session_create(coio.fd, *(uint64_t *) addr);
-	for (;;) {
-		if (admin_dispatch(&coio, iobuf, L) < 0)
-			return;
-		iobuf_gc(iobuf);
-		fiber_gc();
-	}
-}
-
-void
-admin_init(const char *bind_ipaddr, int admin_port)
-{
-	static struct coio_service admin;
-	coio_service_init(&admin, "admin", bind_ipaddr,
-			  admin_port, admin_handler, NULL);
-	evio_service_start(&admin.evio_service);
-}
-
-/*
- * Local Variables:
- * mode: c
- * End:
- * vim: syntax=objc
- */
diff --git a/src/admin.rl b/src/admin.rl
deleted file mode 100644
index c84cf6d2182ada7ba29ab374d8244aa2c262f122..0000000000000000000000000000000000000000
--- a/src/admin.rl
+++ /dev/null
@@ -1,422 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <fiber.h>
-#include <palloc.h>
-#include <salloc.h>
-#include <say.h>
-#include <stat.h>
-#include <tarantool.h>
-#include "lua/init.h"
-#include <recovery.h>
-#include <tbuf.h>
-#include "tarantool/util.h"
-#include <errinj.h>
-#include "coio_buf.h"
-
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-
-#include "box/box.h"
-#include "lua/init.h"
-#include "session.h"
-#include "scoped_guard.h"
-#include "box/space.h"
-
-static const char *help =
-	"available commands:" CRLF
-	" - help" CRLF
-	" - exit" CRLF
-	" - show info" CRLF
-	" - show fiber" CRLF
-	" - show configuration" CRLF
-	" - show index" CRLF
-	" - show slab" CRLF
-	" - show palloc" CRLF
-	" - show stat" CRLF
-	" - save coredump" CRLF
-	" - save snapshot" CRLF
-	" - lua command" CRLF
-	" - reload configuration" CRLF
-	" - show injections (debug mode only)" CRLF
-	" - set injection <name> <state> (debug mode only)" CRLF;
-
-static const char *unknown_command = "unknown command. try typing help." CRLF;
-
-%%{
-	machine admin;
-	write data;
-}%%
-
-struct salloc_stat_admin_cb_ctx {
-	int64_t total_used;
-	int64_t total_used_real;
-	int64_t total_alloc_real;
-	struct tbuf *out;
-};
-
-static int
-salloc_stat_admin_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
-{
-	struct salloc_stat_admin_cb_ctx *ctx = (struct salloc_stat_admin_cb_ctx *) cb_ctx;
-
-	tbuf_printf(ctx->out,
-		    "     - { item_size: %6i, slabs: %6i, items: %11" PRIi64
-		    ", bytes_used: %12" PRIi64 ", waste: %5.2f%%"
-		    ", bytes_free: %12" PRIi64 " }" CRLF,
-		    (int)cstat->item_size,
-		    (int)cstat->slabs,
-		    cstat->items,
-		    cstat->bytes_used,
-		    (double)(cstat->bytes_alloc_real - cstat->bytes_used_real)*100 /
-		    (cstat->bytes_alloc_real + 0.001),
-		    cstat->bytes_free);
-
-	ctx->total_used += cstat->bytes_used;
-	ctx->total_alloc_real += cstat->bytes_alloc_real;
-	ctx->total_used_real += cstat->bytes_used_real;
-	return 0;
-}
-
-static void
-show_slab(struct tbuf *out)
-{
-	struct salloc_stat_admin_cb_ctx cb_ctx;
-	struct slab_arena_stats astat;
-
-	cb_ctx.total_used = 0;
-	cb_ctx.total_used_real = 0;
-	cb_ctx.total_alloc_real = 0;
-	cb_ctx.out = out;
-
-	tbuf_printf(out, "slab statistics:\n  classes:" CRLF);
-
-	salloc_stat(salloc_stat_admin_cb, &astat, &cb_ctx);
-
-	tbuf_printf(out, "  items_used: %.2f%%" CRLF,
-		(double)cb_ctx.total_used / astat.size * 100);
-	tbuf_printf(out, "  arena_used: %.2f%%" CRLF,
-		(double)astat.used / astat.size * 100);
-	tbuf_printf(out, "  waste: %.2f%%" CRLF,
-		    (double)(cb_ctx.total_alloc_real - cb_ctx.total_used_real) / (cb_ctx.total_alloc_real + 0.001) * 100);
-	tbuf_printf(out, "  bytes_waste: %12" PRIi64 CRLF,
-		    (int64_t)((double)cb_ctx.total_used*(cb_ctx.total_alloc_real - cb_ctx.total_used_real) /
-			      (cb_ctx.total_alloc_real + 0.001)));
-}
-
-static void
-end(struct tbuf *out)
-{
-	tbuf_printf(out, "..." CRLF);
-}
-
-static void
-start(struct tbuf *out)
-{
-	tbuf_printf(out, "---" CRLF);
-}
-
-static void
-ok(struct tbuf *out)
-{
-	start(out);
-	tbuf_printf(out, "ok" CRLF);
-	end(out);
-}
-
-static void
-fail(struct tbuf *out, struct tbuf *err)
-{
-	start(out);
-	tbuf_printf(out, "fail:%.*s" CRLF, err->size, (char *)err->data);
-	end(out);
-}
-
-static void
-index_info(struct tbuf *out)
-{
-	tbuf_printf(out, "index:" CRLF);
-	struct space_stat *stat = space_stat();
-	int sp_i = 0;
-	int64_t total_size = 0;
-	while (stat[sp_i].n >= 0) {
-		tbuf_printf(out, "  - space: %" PRIi32 CRLF, stat[sp_i].n);
-		int64_t sp_size = 0;
-		int i;
-		for (i = 0; stat[sp_i].index[i].n >= 0; ++i)
-			sp_size += stat[sp_i].index[i].memsize;
-
-		tbuf_printf(out, "    memsize: %15" PRIi64 CRLF, sp_size);
-		total_size += sp_size;
-		tbuf_printf(out, "    index: " CRLF);
-		for (i = 0; stat[sp_i].index[i].n >= 0; ++i) {
-			tbuf_printf(out, "      - { n: %3d, keys: %15" PRIi64 ", memsize: %15" PRIi64 " }" CRLF,
-				    stat[sp_i].index[i].n, stat[sp_i].index[i].keys, stat[sp_i].index[i].memsize);
-		}
-		++sp_i;
-	}
-	tbuf_printf(out, "memsize:     %15" PRIi64 CRLF, total_size);
-}
-
-static void
-tarantool_info(struct tbuf *out)
-{
-	tbuf_printf(out, "info:" CRLF);
-	tbuf_printf(out, "  version: \"%s\"" CRLF, tarantool_version());
-	tbuf_printf(out, "  uptime: %i" CRLF, (int)tarantool_uptime());
-	tbuf_printf(out, "  pid: %i" CRLF, getpid());
-	tbuf_printf(out, "  logger_pid: %i" CRLF, logger_pid);
-	tbuf_printf(out, "  snapshot_pid: %i" CRLF, snapshot_pid);
-	tbuf_printf(out, "  lsn: %" PRIi64 CRLF,
-		    recovery_state->confirmed_lsn);
-	tbuf_printf(out, "  recovery_lag: %.3f" CRLF,
-		    recovery_state->remote ?
-		    recovery_state->remote->recovery_lag : 0);
-	tbuf_printf(out, "  recovery_last_update: %.3f" CRLF,
-		    recovery_state->remote ?
-		    recovery_state->remote->recovery_last_update_tstamp :0);
-	box_info(out);
-	const char *path = cfg_filename_fullpath;
-	if (path == NULL)
-		path = cfg_filename;
-	tbuf_printf(out, "  config: \"%s\"" CRLF, path);
-}
-
-static int
-show_stat_item(const char *name, int rps, int64_t total, void *ctx)
-{
-	struct tbuf *buf = (struct tbuf *) ctx;
-	int name_len = strlen(name);
-	tbuf_printf(buf,
-		    "  %s:%*s{ rps: %- 6i, total: %- 12" PRIi64 " }" CRLF,
-		    name, 1 + stat_max_name_len - name_len, " ", rps, total);
-	return 0;
-}
-
-void
-show_stat(struct tbuf *buf)
-{
-	tbuf_printf(buf, "statistics:" CRLF);
-	stat_foreach(show_stat_item, buf);
-}
-
-static int
-admin_dispatch(struct ev_io *coio, struct iobuf *iobuf, lua_State *L)
-{
-	struct ibuf *in = &iobuf->in;
-	struct tbuf *out = tbuf_new(fiber_ptr->gc_pool);
-	struct tbuf *err = tbuf_new(fiber_ptr->gc_pool);
-	int cs;
-	char *p, *pe;
-	char *strstart, *strend;
-	bool state;
-
-	while ((pe = (char *) memchr(in->pos, '\n', in->end - in->pos)) == NULL) {
-		if (coio_bread(coio, in, 1) <= 0)
-			return -1;
-	}
-
-	pe++;
-	p = in->pos;
-
-	%%{
-		action show_configuration {
-			start(out);
-			show_cfg(out);
-			end(out);
-		}
-
-		action show_injections {
-			start(out);
-			errinj_info(out);
-			end(out);
-		}
-
-		action help {
-			start(out);
-			tbuf_append(out, help, strlen(help));
-			end(out);
-		}
-
-		action lua {
-			strstart[strend-strstart]='\0';
-			start(out);
-			tarantool_lua(L, out, strstart);
-			end(out);
-		}
-
-		action reload_configuration {
-			if (reload_cfg(err))
-				fail(out, err);
-			else
-				ok(out);
-		}
-
-		action save_snapshot {
-			int ret = snapshot();
-
-			if (ret == 0)
-				ok(out);
-			else {
-				tbuf_printf(err, " can't save snapshot, errno %d (%s)",
-					    ret, strerror(ret));
-
-				fail(out, err);
-			}
-		}
-
-		action set_injection {
-			strstart[strend-strstart] = '\0';
-			if (errinj_set_byname(strstart, state)) {
-				tbuf_printf(err, "can't find error injection '%s'", strstart);
-				fail(out, err);
-			} else {
-				ok(out);
-			}
-		}
-
-		eol = "\n" | "\r\n";
-		show = "sh"("o"("w")?)?;
-		info = "in"("f"("o")?)?;
-		index = ("ind"("e"("x")?)? | "idx");
-		check = "ch"("e"("c"("k")?)?)?;
-		configuration = "co"("n"("f"("i"("g"("u"("r"("a"("t"("i"("o"("n")?)?)?)?)?)?)?)?)?)?)?;
-		fiber = "fi"("b"("e"("r")?)?)?;
-		slab = "sl"("a"("b")?)?;
-		mod = "mo"("d")?;
-		palloc = "pa"("l"("l"("o"("c")?)?)?)?;
-		stat = "st"("a"("t")?)?;
-		plugins = "plugins";
-
-		help = "h"("e"("l"("p")?)?)?;
-		exit = "e"("x"("i"("t")?)?)? | "q"("u"("i"("t")?)?)?;
-		save = "sa"("v"("e")?)?;
-		coredump = "co"("r"("e"("d"("u"("m"("p")?)?)?)?)?)?;
-		snapshot = "sn"("a"("p"("s"("h"("o"("t")?)?)?)?)?)?;
-		string = [^\r\n]+ >{strstart = p;}  %{strend = p;};
-		reload = "re"("l"("o"("a"("d")?)?)?)?;
-		lua = "lu"("a")?;
-
-		set = "se"("t")?;
-		injection = "in"("j"("e"("c"("t"("i"("o"("n")?)?)?)?)?)?)?;
-		injections = injection"s";
-		namech = alnum | punct;
-		name = namech+ >{ strstart = p; }  %{ strend = p; };
-		state_on = "on" %{ state = true; };
-		state_off = "of"("f")? %{ state = false; };
-		state = state_on | state_off;
-
-		commands = (help			%help						|
-			    exit			%{return -1;}					|
-			    lua  " "+ string		%lua						|
-			    show " "+ info		%{start(out); tarantool_info(out); end(out);}	|
-			    show " "+ index		%{start(out); index_info(out); end(out);}	|
-			    show " "+ fiber		%{start(out); fiber_info(out); end(out);}	|
-			    show " "+ configuration 	%show_configuration				|
-			    show " "+ slab		%{start(out); show_slab(out); end(out);}	|
-			    show " "+ palloc		%{start(out); palloc_stat(out); end(out);}	|
-			    show " "+ stat		%{start(out); show_stat(out);end(out);}		|
-			    show " "+ injections	%show_injections                                |
-			    set " "+ injection " "+ name " "+ state	%set_injection                  |
-			    save " "+ coredump		%{coredump(60); ok(out);}			|
-			    save " "+ snapshot		%save_snapshot					|
-			    check " "+ slab		%{slab_validate(); ok(out);}			|
-			    reload " "+ configuration	%reload_configuration);
-
-		main := commands eol;
-		write init;
-		write exec;
-	}%%
-
-	in->pos = pe;
-
-	if (p != pe) {
-		start(out);
-		tbuf_append(out, unknown_command, strlen(unknown_command));
-		end(out);
-	}
-
-	coio_write(coio, out->data, out->size);
-	return 0;
-}
-
-static void
-admin_handler(va_list ap)
-{
-	struct ev_io coio = va_arg(ap, struct ev_io);
-	struct sockaddr_in *addr = va_arg(ap, struct sockaddr_in *);
-	struct iobuf *iobuf = va_arg(ap, struct iobuf *);
-	lua_State *L = lua_newthread(tarantool_L);
-	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
-
-	auto scoped_guard = make_scoped_guard([&] {
-		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
-		evio_close(&coio);
-		iobuf_delete(iobuf);
-		session_destroy(fiber_ptr->sid);
-	});
-
-	/*
-	 * Admin and iproto connections must have a
-	 * session object, representing the state of
-	 * a remote client: it's used in Lua
-	 * stored procedures.
-	 */
-	session_create(coio.fd, *(uint64_t *) addr);
-	for (;;) {
-		if (admin_dispatch(&coio, iobuf, L) < 0)
-			return;
-		iobuf_gc(iobuf);
-		fiber_gc();
-	}
-}
-
-void
-admin_init(const char *bind_ipaddr, int admin_port)
-{
-	static struct coio_service admin;
-	coio_service_init(&admin, "admin", bind_ipaddr,
-			  admin_port, admin_handler, NULL);
-	evio_service_start(&admin.evio_service);
-}
-
-/*
- * Local Variables:
- * mode: c
- * End:
- * vim: syntax=objc
- */
diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc
deleted file mode 100644
index 9e7b2a182248c27bcb956f2a5442809d699b89ad..0000000000000000000000000000000000000000
--- a/src/box/box_lua.cc
+++ /dev/null
@@ -1,1943 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "box_lua.h"
-#include "lua/init.h"
-#include <fiber.h>
-#include "box/box.h"
-#include "request.h"
-#include "txn.h"
-#include "tuple_update.h"
-
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-#include <lj_obj.h>
-#include <lj_ctype.h>
-#include <lj_cdata.h>
-#include <lj_cconv.h>
-#include <arpa/inet.h>
-#include <lib/bit/bit.h>
-} /* extern "C" */
-
-#include "pickle.h"
-#include "tuple.h"
-#include "space.h"
-#include "port.h"
-#include "tbuf.h"
-#include "scoped_guard.h"
-
-/* contents of box.lua, misc.lua, box.net.lua respectively */
-extern char box_lua[],
-	box_net_lua[],
-	misc_lua[];
-static const char *lua_sources[] = {
-	box_lua,
-	box_net_lua,
-	misc_lua,
-	NULL
-};
-
-/**
- * All box connections share the same Lua state. We use
- * Lua coroutines (lua_newthread()) to have multiple
- * procedures running at the same time.
- */
-lua_State *root_L;
-
-/*
- * Functions, exported in box_lua.h should have prefix
- * "box_lua_"; functions, available in Lua "box"
- * should start with "lbox_".
- */
-
-/** {{{ box.tuple Lua library
- *
- * To avoid extra copying between Lua memory and garbage-collected
- * tuple memory, provide a Lua userdata object 'box.tuple'.  This
- * object refers to a tuple instance in the slab allocator, and
- * allows accessing it using Lua primitives (array subscription,
- * iteration, etc.). When Lua object is garbage-collected,
- * tuple reference counter in the slab allocator is decreased,
- * allowing the tuple to be eventually garbage collected in
- * the slab allocator.
- */
-
-static const char *tuplelib_name = "box.tuple";
-static const char *tuple_iteratorlib_name = "box.tuple.iterator";
-
-static void
-lbox_pushtuple(struct lua_State *L, struct tuple *tuple);
-
-static struct tuple *
-lua_totuple(struct lua_State *L, int index);
-
-static inline struct tuple *
-lua_checktuple(struct lua_State *L, int narg)
-{
-	struct tuple *t = *(struct tuple **) luaL_checkudata(L, narg, tuplelib_name);
-	assert(t->refs);
-	return t;
-}
-
-struct tuple *
-lua_istuple(struct lua_State *L, int narg)
-{
-	if (lua_getmetatable(L, narg) == 0)
-		return NULL;
-	luaL_getmetatable(L, tuplelib_name);
-	struct tuple *tuple = 0;
-	if (lua_equal(L, -1, -2))
-		tuple = *(struct tuple **) lua_touserdata(L, narg);
-	lua_pop(L, 2);
-	return tuple;
-}
-
-static int
-lbox_tuple_new(lua_State *L)
-{
-	int argc = lua_gettop(L);
-	if (argc < 1)
-		luaL_error(L, "tuple.new(): bad arguments");
-	struct tuple *tuple = lua_totuple(L, 1);
-	lbox_pushtuple(L, tuple);
-	return 1;
-}
-
-static int
-lbox_tuple_gc(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	tuple_ref(tuple, -1);
-	return 0;
-}
-
-static int
-lbox_tuple_len(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	lua_pushnumber(L, tuple->field_count);
-	return 1;
-}
-
-static int
-lbox_tuple_slice(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	int argc = lua_gettop(L) - 1;
-	uint32_t start, end;
-	int offset;
-
-	/*
-	 * Prepare the range. The second argument is optional.
-	 * If the end is beyond tuple size, adjust it.
-	 * If no arguments, or start > end, return an error.
-	 */
-	if (argc == 0 || argc > 2)
-		luaL_error(L, "tuple.slice(): bad arguments");
-
-	offset = lua_tointeger(L, 2);
-	if (offset >= 0 && offset < tuple->field_count) {
-		start = offset;
-	} else if (offset < 0 && -offset <= tuple->field_count) {
-		start = offset + tuple->field_count;
-	} else {
-		return luaL_error(L, "tuple.slice(): start >= field count");
-	}
-
-	if (argc == 2) {
-		offset = lua_tointeger(L, 3);
-		if (offset > 0 && offset <= tuple->field_count) {
-			end = offset;
-		} else if (offset < 0 && -offset < tuple->field_count) {
-			end = offset + tuple->field_count;
-		} else {
-			return luaL_error(L, "tuple.slice(): end > field count");
-		}
-	} else {
-		end = tuple->field_count;
-	}
-	if (end <= start)
-		return luaL_error(L, "tuple.slice(): start must be less than end");
-
-	struct tuple_iterator it;
-	tuple_rewind(&it, tuple);
-	const char *field;
-	uint32_t len;
-
-	assert(start < tuple->field_count);
-	uint32_t field_no = start;
-	field = tuple_seek(&it, start, &len);
-	while (field && field_no < end) {
-		lua_pushlstring(L, field, len);
-		++field_no;
-		field = tuple_next(&it, &len);
-	}
-	assert(field_no == end);
-	return end - start;
-}
-
-/** A single value on the Lua stack. */
-struct lua_field {
-	const char *data;
-	uint32_t len;
-	union {
-		uint32_t u32;
-		uint64_t u64;
-	};
-	enum field_type type;
-};
-
-/**
- * Convert a value on the lua stack to a Tarantool data type.
- */
-static void
-lua_tofield(lua_State *L, int i, struct lua_field *field)
-{
-	double num;
-	size_t size;
-	switch (lua_type(L, i)) {
-	case LUA_TNUMBER:
-		num = lua_tonumber(L, i);
-		if (num <= UINT32_MAX && num >= INT32_MIN) {
-			field->u32 = (uint32_t) num;
-			field->data = (const char *) &field->u32;
-			field->len = sizeof(uint32_t);
-			field->type = NUM;
-			return;
-		} else {
-			field->u64 = (uint64_t) num;
-			field->data = (const char *) &field->u64;
-			field->len = sizeof(uint64_t);
-			field->type = NUM64;
-			return;
-		}
-	case LUA_TCDATA:
-		field->u64 = tarantool_lua_tointeger64(L, i);
-		field->data = (const char *) &field->u64;
-		field->len = sizeof(uint64_t);
-		field->type = NUM64;
-		return;
-	case LUA_TBOOLEAN:
-		if (lua_toboolean(L, i)) {
-			field->data = "true";
-			field->len = 4;
-		} else {
-			field->data = "false";
-			field->len = 5;
-		}
-		field->type = STRING;
-		return;
-	case LUA_TNIL:
-		field->data = "nil";
-		field->len = 3;
-		field->type = STRING;
-		return;
-	case LUA_TSTRING:
-		field->data = lua_tolstring(L, i, &size);
-		field->len = (uint32_t) size;
-		field->type = STRING;
-		return;
-	default:
-		field->data = NULL;
-		field->len = 0;
-		field->type = UNKNOWN;
-		return;
-	}
-}
-
-/**
- * @brief A wrapper for lua_tofield that raises an error if Lua type can not
- * be converted to lua_field structure
- * @param L stack
- * @param index stack index
- * @param field conversion result
- * @sa lua_tofield()
- */
-static inline void
-lua_checkfield(lua_State *L, int i, struct lua_field *field)
-{
-	lua_tofield(L, i, field);
-	if (unlikely(field->type == UNKNOWN))
-		luaL_error(L, "unsupported Lua type '%s'",
-			   lua_typename(L, lua_type(L, i)));
-}
-
-/**
- * Tuple transforming function.
- *
- * Remove the fields designated by 'offset' and 'len' from an tuple,
- * and replace them with the elements of supplied data fields,
- * if any.
- *
- * Function returns newly allocated tuple.
- * It does not change any parent tuple data.
- */
-static int
-lbox_tuple_transform(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	int argc = lua_gettop(L);
-	if (argc < 3)
-		luaL_error(L, "tuple.transform(): bad arguments");
-	lua_Integer offset = lua_tointeger(L, 2);  /* Can be negative and can be > INT_MAX */
-	lua_Integer field_count = lua_tointeger(L, 3);
-
-	/* validate offset and len */
-	if (offset < 0) {
-		if (-offset > tuple->field_count)
-			luaL_error(L, "tuple.transform(): offset is out of bound");
-		offset += tuple->field_count;
-	} else if (offset > tuple->field_count) {
-		offset = tuple->field_count;
-	}
-	if (field_count < 0)
-		luaL_error(L, "tuple.transform(): len is negative");
-	if (field_count > tuple->field_count - offset)
-		field_count = tuple->field_count - offset;
-
-	assert(offset + field_count <= tuple->field_count);
-
-	/*
-	 * Calculate the number of operations and length of UPDATE expression
-	 */
-	uint32_t op_cnt = 0;
-	if (offset < tuple->field_count && field_count > 0)
-		op_cnt++;
-	if (argc > 3)
-		op_cnt += argc - 3;
-
-	if (op_cnt == 0) {
-		/* tuple_update() does not accept an empty operation list. */
-		lbox_pushtuple(L, tuple);
-		return 1;
-	}
-
-	PallocGuard palloc_guard(fiber_ptr->gc_pool);
-
-	/*
-	 * Prepare UPDATE expression
-	 */
-	struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-	tbuf_append(b, (char *) &op_cnt, sizeof(op_cnt));
-	if (field_count > 0) {
-		tbuf_ensure(b, 2 * sizeof(uint32_t) + 1 + 5);
-
-		/* offset */
-		char *data = pack_u32(b->data + b->size, offset);
-
-		/* operation */
-		*(data++) = UPDATE_OP_DELETE;
-
-		/* field: count */
-		data = pack_varint32(data, sizeof(uint32_t));
-		data = pack_u32(data, field_count);
-
-		assert(data <= b->data + b->capacity);
-		b->size = data - b->data;
-	}
-
-	for (int i = argc ; i > 3; i--) {
-		struct lua_field field;
-		lua_checkfield(L, i, &field);
-		tbuf_ensure(b, sizeof(uint32_t) + 1 + 5 + field.len);
-
-		/* offset */
-		char *data = pack_u32(b->data + b->size, offset);
-
-		/* operation */
-		*data++ = UPDATE_OP_INSERT;
-
-		/* field */
-		data = pack_lstr(data, field.data, field.len);
-
-		assert(data <= b->data + b->capacity);
-		b->size = data - b->data;
-	}
-
-	/* Execute tuple_update */
-	struct tuple *new_tuple = tuple_update(tuple_format_ber,
-					       palloc_region_alloc,
-					       fiber_ptr->gc_pool,
-					       tuple, tbuf_str(b), tbuf_end(b));
-	lbox_pushtuple(L, new_tuple);
-	return 1;
-}
-
-/*
- * Tuple find function.
- *
- * Find each or one tuple field according to the specified key.
- *
- * Function returns indexes of the tuple fields that match
- * key criteria.
- *
- */
-static int
-tuple_find(struct lua_State *L, struct tuple *tuple, size_t offset,
-	   const char *key, size_t key_size,
-	   bool all)
-{
-	int top = lua_gettop(L);
-	int idx = offset;
-
-	struct tuple_iterator it;
-	tuple_rewind(&it, tuple);
-	uint32_t len;
-	const char *field = tuple_seek(&it, idx, &len);
-	for (; field; field = tuple_next(&it, &len)) {
-		if (len == key_size && (memcmp(field, key, len) == 0)) {
-			lua_pushinteger(L, idx);
-			if (!all)
-				break;
-		}
-		idx++;
-	}
-	return lua_gettop(L) - top;
-}
-
-static int
-lbox_tuple_find_do(struct lua_State *L, bool all)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	int argc = lua_gettop(L);
-	size_t offset = 0;
-	switch (argc - 1) {
-	case 1: break;
-	case 2:
-		offset = lua_tointeger(L, 2);
-		break;
-	default:
-		luaL_error(L, "tuple.find(): bad arguments");
-	}
-
-	struct lua_field field;
-	lua_checkfield(L, argc, &field);
-
-	return tuple_find(L, tuple, offset, field.data, field.len, all);
-}
-
-static int
-lbox_tuple_find(struct lua_State *L)
-{
-	return lbox_tuple_find_do(L, false);
-}
-
-static int
-lbox_tuple_findall(struct lua_State *L)
-{
-	return lbox_tuple_find_do(L, true);
-}
-
-static int
-lbox_tuple_unpack(struct lua_State *L)
-{
-	int argc = lua_gettop(L);
-	(void) argc;
-	struct tuple *tuple = lua_checktuple(L, 1);
-
-	struct tuple_iterator it;
-	tuple_rewind(&it, tuple);
-	const char *field;
-
-	uint32_t len;
-	while ((field = tuple_next(&it, &len)))
-		lua_pushlstring(L, field, len);
-
-	assert(lua_gettop(L) == argc + tuple->field_count);
-	return tuple->field_count;
-}
-
-static int
-lbox_tuple_totable(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	lua_newtable(L);
-	int index = 1;
-
-	struct tuple_iterator it;
-	tuple_rewind(&it, tuple);
-	const char *field;
-	uint32_t len;
-	while ((field = tuple_next(&it, &len))) {
-		lua_pushnumber(L, index++);
-		lua_pushlstring(L, field, len);
-		lua_rawset(L, -3);
-	}
-	return 1;
-}
-
-/**
- * Implementation of tuple __index metamethod.
- *
- * Provides operator [] access to individual fields for integer
- * indexes, as well as searches and invokes metatable methods
- * for strings.
- */
-static int
-lbox_tuple_index(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	/* For integer indexes, implement [] operator */
-	if (lua_isnumber(L, 2)) {
-		int i = luaL_checkint(L, 2);
-		if (i >= tuple->field_count)
-			luaL_error(L, "%s: index %d is out of bounds (0..%d)",
-				   tuplelib_name, i, tuple->field_count-1);
-		uint32_t len = 0;
-		const char *field = tuple_field(tuple, i, &len);
-		lua_pushlstring(L, field, len);
-		return 1;
-	}
-	/* If we got a string, try to find a method for it. */
-	const char *sz = luaL_checkstring(L, 2);
-	lua_getmetatable(L, 1);
-	lua_getfield(L, -1, sz);
-	return 1;
-}
-
-static int
-lbox_tuple_tostring(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	/* @todo: print the tuple */
-	size_t allocated = palloc_allocated(fiber_ptr->gc_pool);
-	struct tbuf *tbuf = tbuf_new(fiber_ptr->gc_pool);
-	tuple_print(tbuf, tuple);
-	lua_pushlstring(L, tbuf->data, tbuf->size);
-	ptruncate(fiber_ptr->gc_pool, allocated);
-	return 1;
-}
-
-static void
-lbox_pushtuple(struct lua_State *L, struct tuple *tuple)
-{
-	if (tuple) {
-		struct tuple **ptr = (struct tuple **)
-				lua_newuserdata(L, sizeof(*ptr));
-		luaL_getmetatable(L, tuplelib_name);
-		lua_setmetatable(L, -2);
-		*ptr = tuple;
-		tuple_ref(tuple, 1);
-	} else {
-		lua_pushnil(L);
-	}
-}
-
-/**
- * Sequential access to tuple fields. Since tuple is a list-like
- * structure, iterating over tuple fields is faster
- * than accessing fields using an index.
- */
-static int
-lbox_tuple_next(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	int argc = lua_gettop(L) - 1;
-
-	struct tuple_iterator *it = NULL;
-	if (argc == 0 || (argc == 1 && lua_type(L, 2) == LUA_TNIL)) {
-		it = (struct tuple_iterator *) lua_newuserdata(L, sizeof(*it));
-		assert (it != NULL);
-		luaL_getmetatable(L, tuple_iteratorlib_name);
-		lua_setmetatable(L, -2);
-		tuple_rewind(it, tuple);
-	} else if (argc == 1 && lua_type(L, 2) == LUA_TUSERDATA) {
-		it = (struct tuple_iterator *)
-			luaL_checkudata(L, 2, tuple_iteratorlib_name);
-		assert (it != NULL);
-		lua_pushvalue(L, 2);
-	} else {
-		return luaL_error(L, "tuple.next(): bad arguments");
-	}
-
-	uint32_t len;
-	const char *field = tuple_next(it, &len);
-	if (field == NULL) {
-		lua_pop(L, 1);
-		lua_pushnil(L);
-		return 1;
-	}
-
-	lua_pushlstring(L, field, len);
-	return 2;
-}
-
-/** Iterator over tuple fields. Adapt lbox_tuple_next
- * to Lua iteration conventions.
- */
-static int
-lbox_tuple_pairs(struct lua_State *L)
-{
-	lua_pushcfunction(L, lbox_tuple_next);
-	lua_pushvalue(L, -2); /* tuple */
-	lua_pushnil(L);
-	return 3;
-}
-
-
-/** tuple:bsize()
- *
- */
-static int
-lbox_tuple_bsize(struct lua_State *L)
-{
-	struct tuple *tuple = lua_checktuple(L, 1);
-	lua_pushnumber(L, tuple->bsize);
-	return 1;
-}
-
-static const struct luaL_reg lbox_tuple_meta[] = {
-	{"__gc", lbox_tuple_gc},
-	{"__len", lbox_tuple_len},
-	{"__index", lbox_tuple_index},
-	{"__tostring", lbox_tuple_tostring},
-	{"next", lbox_tuple_next},
-	{"pairs", lbox_tuple_pairs},
-	{"slice", lbox_tuple_slice},
-	{"transform", lbox_tuple_transform},
-	{"find", lbox_tuple_find},
-	{"findall", lbox_tuple_findall},
-	{"unpack", lbox_tuple_unpack},
-	{"totable", lbox_tuple_totable},
-	{"bsize", lbox_tuple_bsize},
-	{NULL, NULL}
-};
-
-static const struct luaL_reg lbox_tuplelib[] = {
-	{"new", lbox_tuple_new},
-	{NULL, NULL}
-};
-
-static const struct luaL_reg lbox_tuple_iterator_meta[] = {
-	{NULL, NULL}
-};
-
-/* }}} */
-
-/** {{{ box.index Lua library: access to spaces and indexes
- */
-
-static const char *indexlib_name = "box.index";
-static const char *iteratorlib_name = "box.index.iterator";
-
-static struct iterator *
-lbox_checkiterator(struct lua_State *L, int i)
-{
-	struct iterator **it = (struct iterator **)
-			luaL_checkudata(L, i, iteratorlib_name);
-	assert(it != NULL);
-	return *it;
-}
-
-static void
-lbox_pushiterator(struct lua_State *L, Index *index,
-		  struct iterator *it, enum iterator_type type,
-		  const char *key, size_t size, int part_count)
-{
-	struct lbox_iterator_udata {
-		struct iterator *it;
-		char key[];
-	};
-
-	struct lbox_iterator_udata *udata = (struct lbox_iterator_udata *)
-		lua_newuserdata(L, sizeof(*udata) + size);
-	luaL_getmetatable(L, iteratorlib_name);
-	lua_setmetatable(L, -2);
-
-	udata->it = it;
-	if (key) {
-		memcpy(udata->key, key, size);
-		key = udata->key;
-	}
-	key_validate(index->key_def, type, key, part_count);
-	index->initIterator(it, type, key, part_count);
-}
-
-static int
-lbox_iterator_gc(struct lua_State *L)
-{
-	struct iterator *it = lbox_checkiterator(L, -1);
-	it->free(it);
-	return 0;
-}
-
-static Index *
-lua_checkindex(struct lua_State *L, int i)
-{
-	Index **index = (Index **) luaL_checkudata(L, i, indexlib_name);
-	assert(index != NULL);
-	return *index;
-}
-
-static int
-lbox_index_new(struct lua_State *L)
-{
-	int n = luaL_checkint(L, 1); /* get space id */
-	int idx = luaL_checkint(L, 2); /* get index id in */
-	/* locate the appropriate index */
-	struct space *sp = space_find(n);
-	Index *index = index_find(sp, idx);
-
-	/* create a userdata object */
-	void **ptr = (void **) lua_newuserdata(L, sizeof(void *));
-	*ptr = index;
-	/* set userdata object metatable to indexlib */
-	luaL_getmetatable(L, indexlib_name);
-	lua_setmetatable(L, -2);
-
-	return 1;
-}
-
-static int
-lbox_index_tostring(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	lua_pushfstring(L, "index %d in space %d",
-			index_n(index), space_n(index->space));
-	return 1;
-}
-
-static int
-lbox_index_len(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	lua_pushinteger(L, index->size());
-	return 1;
-}
-
-static int
-lbox_index_part_count(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	lua_pushinteger(L, index->key_def->part_count);
-	return 1;
-}
-
-static int
-lbox_index_min(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	lbox_pushtuple(L, index->min());
-	return 1;
-}
-
-static int
-lbox_index_max(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	lbox_pushtuple(L, index->max());
-	return 1;
-}
-
-static int
-lbox_index_random(struct lua_State *L)
-{
-	if (lua_gettop(L) != 2 || lua_isnil(L, 2))
-		luaL_error(L, "Usage: index:random((uint32) rnd)");
-
-	Index *index = lua_checkindex(L, 1);
-	uint32_t rnd = lua_tointeger(L, 2);
-	lbox_pushtuple(L, index->random(rnd));
-	return 1;
-}
-
-
-/*
- * Lua iterator over a Taratnool/Box index.
- *
- *	(iteration_state, tuple) = index.next(index, [params])
- *
- * When [params] are absent or nil
- * returns a pointer to a new ALL iterator and
- * to the first tuple (or nil, if the index is
- * empty).
- *
- * When [params] is a userdata,
- * i.e. we're inside an iteration loop, retrieves
- * the next tuple from the iterator.
- *
- * Otherwise, [params] can be used to seed
- * a new iterator with iterator type and
- * type-specific arguments. For exaple,
- * for GE iterator, a list of Lua scalars
- * cann follow the box.index.GE: this will
- * start iteration from the offset specified by
- * the given (multipart) key.
- *
- * @return Returns an iterator object, either created
- *         or taken from Lua stack.
- */
-
-static inline struct iterator *
-lbox_create_iterator(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	int argc = lua_gettop(L);
-
-	/* Create a new iterator. */
-	PallocGuard palloc_guard(fiber_ptr->gc_pool);
-	enum iterator_type type = ITER_ALL;
-	uint32_t key_part_count = 0;
-	const char *key = NULL;
-	size_t key_size = 0;
-	if (argc == 1 || (argc == 2 && lua_type(L, 2) == LUA_TNIL)) {
-		/*
-		 * Nothing or nil on top of the stack,
-		 * iteration over entire range from the
-		 * beginning (ITER_ALL).
-		 */
-	} else {
-		type = (enum iterator_type) luaL_checkint(L, 2);
-		if (type < ITER_ALL || type >= iterator_type_MAX)
-			luaL_error(L, "unknown iterator type: %d", type);
-		/* What else do we have on the stack? */
-		if (argc == 2 || (argc == 3 && lua_type(L, 3) == LUA_TNIL)) {
-			/* Nothing */
-		} else if (argc == 3 && lua_type(L, 3) == LUA_TUSERDATA) {
-			/* Tuple. */
-			struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-			struct tuple *tuple = lua_checktuple(L, 2);
-			key_part_count = tuple->field_count;
-			tuple_to_tbuf(tuple, b);
-			key = b->data;
-			key_size = b->size;
-		} else {
-			/* Single or multi- part key. */
-			struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-			key_part_count = argc - 2;
-			struct lua_field field;
-			for (uint32_t i = 0; i < key_part_count; i++) {
-				lua_checkfield(L, i + 3, &field);
-				tbuf_ensure(b, field.len + 5);
-				char *data = pack_lstr(b->data + b->size,
-							field.data, field.len);
-				b->size = data - b->data;
-			}
-			key = b->data;
-			key_size = b->size;
-		}
-		/*
-		 * We allow partially specified keys for TREE
-		 * indexes. HASH indexes can only use single-part
-		 * keys.
-		*/
-		if (key_part_count > index->key_def->part_count)
-			luaL_error(L, "Key part count %d"
-				   " is greater than index part count %d",
-				   key_part_count, index->key_def->part_count);
-		if (key_size == 0)
-			key = NULL;
-	}
-	struct iterator *it = index->allocIterator();
-	lbox_pushiterator(L, index, it, type, key, key_size,
-			  key_part_count);
-	return it;
-}
-
-/**
- * Lua-style next() function, for use in pairs().
- * @example:
- * for k, v in box.space[0].index[0].idx.next, box.space[0].index[0].idx, nil do
- *	print(v)
- * end
- */
-static int
-lbox_index_next(struct lua_State *L)
-{
-	int argc = lua_gettop(L);
-	struct iterator *it = NULL;
-	if (argc == 2 && lua_type(L, 2) == LUA_TUSERDATA) {
-		/*
-		 * Apart from the index itself, we have only one
-		 * other argument, and it's a userdata: must be
-		 * iteration state created before.
-		 */
-		it = lbox_checkiterator(L, 2);
-	} else {
-		it = lbox_create_iterator(L);
-	}
-	struct tuple *tuple = it->next(it);
-	/* If tuple is NULL, pushes nil as end indicator. */
-	lbox_pushtuple(L, tuple);
-	return tuple ? 2 : 1;
-}
-
-/** iterator() closure function. */
-static int
-lbox_index_iterator_closure(struct lua_State *L)
-{
-	/* Extract closure arguments. */
-	struct iterator *it = lbox_checkiterator(L, lua_upvalueindex(1));
-
-	struct tuple *tuple = it->next(it);
-
-	/* If tuple is NULL, push nil as end indicator. */
-	lbox_pushtuple(L, tuple);
-	return 1;
-}
-
-/**
- * @brief Create iterator closure over a Taratnool/Box index.
- * @example lua it = box.space[0].index[0]:iterator(box.index.GE, 1);
- *   print(it(), it()).
- * @param L lua stack
- * @see http://www.lua.org/pil/7.1.html
- * @return number of return values put on the stack
- */
-static int
-lbox_index_iterator(struct lua_State *L)
-{
-	/* Create iterator and push it onto the stack. */
-	(void) lbox_create_iterator(L);
-	lua_pushcclosure(L, &lbox_index_iterator_closure, 1);
-	return 1;
-}
-
-
-/**
- * Lua index subtree count function.
- * Iterate over an index, count the number of tuples which equal the
- * provided search criteria. The argument can either point to a
- * tuple, a key, or one or more key parts. Returns the number of matched
- * tuples.
- */
-static int
-lbox_index_count(struct lua_State *L)
-{
-	Index *index = lua_checkindex(L, 1);
-	int argc = lua_gettop(L) - 1;
-	if (argc == 0)
-		luaL_error(L, "index.count(): one or more arguments expected");
-
-	/* preparing single or multi-part key */
-	PallocGuard palloc_guard(fiber_ptr->gc_pool);
-	uint32_t key_part_count = 0;
-	const char *key = NULL;
-	if (argc == 1 && lua_type(L, 2) == LUA_TUSERDATA) {
-		/* Searching by tuple. */
-		struct tuple *tuple = lua_checktuple(L, 2);
-		struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-		tuple_to_tbuf(tuple, b);
-		key_part_count = tuple->field_count;
-		key = b->data;
-	} else {
-		/* Single or multi- part key. */
-		struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-		key_part_count = argc;
-		struct lua_field field;
-		for (uint32_t i = 0; i < key_part_count; i++) {
-			lua_checkfield(L, i + 2, &field);
-			tbuf_ensure(b, field.len + 5);
-			char *data = pack_lstr(b->data + b->size,
-						field.data, field.len);
-			b->size = data - b->data;
-		}
-		key = b->data;
-	}
-	if (key_part_count == 0)
-		key = NULL;
-	uint32_t count = 0;
-
-	key_validate(index->key_def, ITER_EQ, key, key_part_count);
-	/* Prepare index iterator */
-	struct iterator *it = index->position();
-	index->initIterator(it, ITER_EQ, key, key_part_count);
-	/* Iterate over the index and count tuples. */
-	struct tuple *tuple;
-	while ((tuple = it->next(it)) != NULL)
-		count++;
-
-	/* Return subtree size */
-	lua_pushnumber(L, count);
-	return 1;
-}
-
-static const struct luaL_reg lbox_index_meta[] = {
-	{"__tostring", lbox_index_tostring},
-	{"__len", lbox_index_len},
-	{"part_count", lbox_index_part_count},
-	{"min", lbox_index_min},
-	{"max", lbox_index_max},
-	{"random", lbox_index_random},
-	{"next", lbox_index_next},
-	{"iterator", lbox_index_iterator},
-	{"count", lbox_index_count},
-	{NULL, NULL}
-};
-
-static const struct luaL_reg indexlib [] = {
-	{"new", lbox_index_new},
-	{NULL, NULL}
-};
-
-static const struct luaL_reg lbox_iterator_meta[] = {
-	{"__gc", lbox_iterator_gc},
-	{NULL, NULL}
-};
-
-/* }}} */
-
-/** {{{ Lua I/O: facilities to intercept box output
- * and push into Lua stack.
- */
-
-struct port_lua
-{
-	struct port_vtab *vtab;
-	struct lua_State *L;
-};
-
-static inline struct port_lua *
-port_lua(struct port *port) { return (struct port_lua *) port; }
-
-/*
- * For addU32/dupU32 do nothing -- the only uint32_t Box can give
- * us is tuple count, and we don't need it, since we intercept
- * everything into Lua stack first.
- * @sa port_add_lua_multret
- */
-
-static void
-port_lua_add_tuple(struct port *port, struct tuple *tuple,
-		   uint32_t flags __attribute__((unused)))
-{
-	lua_State *L = port_lua(port)->L;
-	try {
-		lbox_pushtuple(L, tuple);
-	} catch (...) {
-		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
-	}
-}
-
-struct port_vtab port_lua_vtab = {
-	port_lua_add_tuple,
-	null_port_eof,
-};
-
-static struct port *
-port_lua_create(struct lua_State *L)
-{
-	struct port_lua *port = (struct port_lua *)
-			palloc(fiber_ptr->gc_pool, sizeof(struct port_lua));
-	port->vtab = &port_lua_vtab;
-	port->L = L;
-	return (struct port *) port;
-}
-
-/**
- * Convert a Lua table to a tuple with as little
- * overhead as possible.
- */
-static struct tuple *
-lua_table_to_tuple(struct lua_State *L, int index)
-{
-	uint32_t field_count = 0;
-	uint32_t tuple_len = 0;
-	struct lua_field field;
-
-	/** First go: calculate tuple length. */
-	lua_pushnil(L);  /* first key */
-	while (lua_next(L, index) != 0) {
-		++field_count;
-
-		lua_tofield(L, -1, &field);
-		if (field.type == UNKNOWN) {
-			tnt_raise(ClientError, ER_PROC_RET,
-				  lua_typename(L, lua_type(L, -1)));
-		}
-		tuple_len += field.len + varint32_sizeof(field.len);
-		lua_pop(L, 1);
-	}
-	struct tuple *tuple = tuple_alloc(tuple_format_ber, tuple_len);
-	/*
-	 * Important: from here and on if there is an exception,
-	 * the tuple is leaked.
-	 */
-	tuple->field_count = field_count;
-	char *pos = tuple->data;
-
-	/* Second go: store data in the tuple. */
-
-	lua_pushnil(L);  /* first key */
-	while (lua_next(L, index) != 0) {
-		lua_tofield(L, -1, &field);
-		pos = pack_lstr(pos, field.data, field.len);
-		lua_pop(L, 1);
-	}
-	return tuple;
-}
-
-static struct tuple*
-lua_totuple(struct lua_State *L, int index)
-{
-	int type = lua_type(L, index);
-	struct tuple *tuple;
-	struct lua_field field;
-	lua_tofield(L, index, &field);
-	if (field.type != UNKNOWN) {
-		tuple = tuple_alloc(tuple_format_ber,
-				    field.len + varint32_sizeof(field.len));
-		tuple->field_count = 1;
-		pack_lstr(tuple->data, field.data, field.len);
-		return tuple;
-	}
-	switch (type) {
-	case LUA_TTABLE:
-	{
-		return lua_table_to_tuple(L, index);
-	}
-	case LUA_TUSERDATA:
-	{
-		tuple = lua_istuple(L, index);
-		if (tuple)
-			return tuple;
-	}
-	default:
-		/*
-		 * LUA_TNONE, LUA_TTABLE, LUA_THREAD, LUA_TFUNCTION
-		 */
-		tnt_raise(ClientError, ER_PROC_RET, lua_typename(L, type));
-		break;
-	}
-}
-
-static void
-port_add_lua_ret(struct port *port, struct lua_State *L, int index)
-{
-	struct tuple *tuple = lua_totuple(L, index);
-	auto scoped_guard = make_scoped_guard([=] {
-		if (tuple->refs == 0)
-			tuple_free(tuple);
-	});
-	port_add_tuple(port, tuple, BOX_RETURN_TUPLE);
-}
-
-/**
- * Add all elements from Lua stack to fiber iov.
- *
- * To allow clients to understand a complex return from
- * a procedure, we are compatible with SELECT protocol,
- * and return the number of return values first, and
- * then each return value as a tuple.
- *
- * If a Lua stack contains at least one scalar, each
- * value on the stack is converted to a tuple. A Lua
- * is converted to a tuple with multiple fields.
- *
- * If the stack is a Lua table, each member of which is
- * not scalar, each member of the table is converted to
- * a tuple. This way very large lists of return values can
- * be used, since Lua stack size is limited by 8000 elements,
- * while Lua table size is pretty much unlimited.
- */
-static void
-port_add_lua_multret(struct port *port, struct lua_State *L)
-{
-	int nargs = lua_gettop(L);
-	/** Check if we deal with a table of tables. */
-	if (nargs == 1 && lua_istable(L, 1)) {
-		/*
-		 * The table is not empty and consists of tables
-		 * or tuples. Treat each table element as a tuple,
-		 * and push it.
-		 */
-		lua_pushnil(L);
-		int has_keys = lua_next(L, 1);
-		if (has_keys  &&
-		    (lua_istable(L, -1) || lua_isuserdata(L, -1))) {
-
-			do {
-				port_add_lua_ret(port, L, lua_gettop(L));
-				lua_pop(L, 1);
-			} while (lua_next(L, 1));
-			return;
-		} else if (has_keys) {
-			lua_pop(L, 1);
-		}
-	}
-	for (int i = 1; i <= nargs; ++i) {
-		port_add_lua_ret(port, L, i);
-	}
-}
-
-/* }}} */
-
-/**
- * The main extension provided to Lua by Tarantool/Box --
- * ability to call INSERT/UPDATE/SELECT/DELETE from within
- * a Lua procedure.
- *
- * This is a low-level API, and it expects
- * all arguments to be packed in accordance
- * with the binary protocol format (iproto
- * header excluded).
- *
- * Signature:
- * box.process(op_code, request)
- */
-static int
-lbox_process(lua_State *L)
-{
-	uint32_t op = lua_tointeger(L, 1); /* Get the first arg. */
-	size_t sz;
-	const char *req = luaL_checklstring(L, 2, &sz); /* Second arg. */
-	if (op == CALL) {
-		/*
-		 * We should not be doing a CALL from within a CALL.
-		 * To invoke one stored procedure from another, one must
-		 * do it in Lua directly. This deals with
-		 * infinite recursion, stack overflow and such.
-		 */
-		return luaL_error(L, "box.process(CALL, ...) is not allowed");
-	}
-	int top = lua_gettop(L); /* to know how much is added by rw_callback */
-
-	size_t allocated_size = palloc_allocated(fiber_ptr->gc_pool);
-	struct port *port_lua = port_lua_create(L);
-	try {
-		box_process(port_lua, op, req, sz);
-
-		/*
-		 * This only works as long as port_lua doesn't
-		 * use fiber->cleanup and fiber_ptr->gc_pool.
-		 */
-		ptruncate(fiber_ptr->gc_pool, allocated_size);
-	} catch (const Exception& e) {
-		ptruncate(fiber_ptr->gc_pool, allocated_size);
-		throw;
-	}
-	return lua_gettop(L) - top;
-}
-
-static int
-lbox_raise(lua_State *L)
-{
-	if (lua_gettop(L) != 2)
-		luaL_error(L, "box.raise(): bad arguments");
-	uint32_t code = lua_tointeger(L, 1);
-	if (!code)
-		luaL_error(L, "box.raise(): unknown error code");
-	const char *str = lua_tostring(L, 2);
-	tnt_raise(ClientError, str, code);
-	return 0;
-}
-
-/**
- * A helper to find a Lua function by name and put it
- * on top of the stack.
- */
-static int
-box_lua_find(lua_State *L, const char *name, const char *name_end)
-{
-	int index = LUA_GLOBALSINDEX;
-	int objstack = 0;
-	const char *start = name, *end;
-
-	while ((end = (const char *) memchr(start, '.', name_end - start))) {
-		lua_checkstack(L, 3);
-		lua_pushlstring(L, start, end - start);
-		lua_gettable(L, index);
-		if (! lua_istable(L, -1))
-			tnt_raise(ClientError, ER_NO_SUCH_PROC,
-				  name_end - name, name);
-		start = end + 1; /* next piece of a.b.c */
-		index = lua_gettop(L); /* top of the stack */
-	}
-
-	/* box.something:method */
-	if ((end = (const char *) memchr(start, ':', name_end - start))) {
-		lua_checkstack(L, 3);
-		lua_pushlstring(L, start, end - start);
-		lua_gettable(L, index);
-		if (! (lua_istable(L, -1) ||
-			lua_islightuserdata(L, -1) || lua_isuserdata(L, -1) ))
-				tnt_raise(ClientError, ER_NO_SUCH_PROC,
-					  name_end - name, name);
-		start = end + 1; /* next piece of a.b.c */
-		index = lua_gettop(L); /* top of the stack */
-		objstack = index;
-	}
-
-
-	lua_pushlstring(L, start, name_end - start);
-	lua_gettable(L, index);
-	if (! lua_isfunction(L, -1)) {
-		/* lua_call or lua_gettable would raise a type error
-		 * for us, but our own message is more verbose. */
-		tnt_raise(ClientError, ER_NO_SUCH_PROC,
-			  name_end - name, name);
-	}
-	/* setting stack that it would contain only
-	 * the function pointer. */
-	if (index != LUA_GLOBALSINDEX) {
-		if (objstack == 0) {        /* no object, only a function */
-			lua_replace(L, 1);
-		} else if (objstack == 1) { /* just two values, swap them */
-			lua_insert(L, -2);
-		} else {		    /* long path */
-			lua_insert(L, 1);
-			lua_insert(L, 2);
-			objstack = 1;
-		}
-		lua_settop(L, 1 + objstack);
-	}
-	return 1 + objstack;
-}
-
-
-/**
- * A helper to find lua stored procedures for box.call.
- * box.call iteslf is pure Lua, to avoid issues
- * with infinite call recursion smashing C
- * thread stack.
- */
-
-static int
-lbox_call_loadproc(struct lua_State *L)
-{
-	const char *name;
-	size_t name_len;
-	name = lua_tolstring(L, 1, &name_len);
-	box_lua_find(L, name, name + name_len);
-	return 1;
-}
-
-/**
- * Invoke a Lua stored procedure from the binary protocol
- * (implementation of 'CALL' command code).
- */
-void
-box_lua_execute(struct request *request, struct port *port)
-{
-	const char **reqpos = &request->data;
-	const char *reqend = request->data + request->len;
-	lua_State *L = lua_newthread(root_L);
-	int coro_ref = luaL_ref(root_L, LUA_REGISTRYINDEX);
-	/* Request flags: not used. */
-	(void) (pick_u32(reqpos, reqend));
-
-	try {
-		auto scoped_guard = make_scoped_guard([=] {
-			/*
-			 * Allow the used coro to be garbage collected.
-			 * @todo: cache and reuse it instead.
-			 */
-			luaL_unref(root_L, LUA_REGISTRYINDEX, coro_ref);
-		});
-
-		uint32_t field_len;
-		/* proc name */
-		const char *field = pick_field_str(reqpos, reqend, &field_len);
-		box_lua_find(L, field, field + field_len);
-		/* Push the rest of args (a tuple). */
-		uint32_t nargs = pick_u32(reqpos, reqend);
-		luaL_checkstack(L, nargs, "call: out of stack");
-		for (int i = 0; i < nargs; i++) {
-			field = pick_field_str(reqpos, reqend, &field_len);
-			lua_pushlstring(L, field, field_len);
-		}
-		lua_call(L, nargs, LUA_MULTRET);
-		/* Send results of the called procedure to the client. */
-		port_add_lua_multret(port, L);
-	} catch (const Exception& e) {
-		throw;
-	} catch (...) {
-		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
-	}
-}
-
-static void
-box_index_init_iterator_types(struct lua_State *L, int idx)
-{
-	for (int i = 0; i < iterator_type_MAX; i++) {
-		assert(strncmp(iterator_type_strs[i], "ITER_", 5) == 0);
-		lua_pushnumber(L, i);
-		/* cut ITER_ prefix from enum name */
-		lua_setfield(L, idx, iterator_type_strs[i] + 5);
-	}
-}
-
-/**
- * Convert box.pack() format specifier to Tarantool
- * binary protocol UPDATE opcode
- */
-static char format_to_opcode(char format)
-{
-	switch (format) {
-	case '=': return 0;
-	case '+': return 1;
-	case '&': return 2;
-	case '^': return 3;
-	case '|': return 4;
-	case ':': return 5;
-	case '#': return 6;
-	case '!': return 7;
-	case '-': return 8;
-	default: return format;
-	}
-}
-
-/**
- * Counterpart to @a format_to_opcode
- */
-static char opcode_to_format(char opcode)
-{
-	switch (opcode) {
-	case 0: return '=';
-	case 1: return '+';
-	case 2: return '&';
-	case 3: return '^';
-	case 4: return '|';
-	case 5: return ':';
-	case 6: return '#';
-	case 7: return '!';
-	case 8: return '-';
-	default: return opcode;
-	}
-}
-
-enum { BOX_PACK_MAXNESTING = 16 }; /* Max nesting levels. */
-
-/*
- * This function is recursive. \a level param is needed to control
- * the maximum recursion level.
- */
-static int
-luaL_packsize_r(struct lua_State *L, int index, int level)
-{
-	switch (lua_type(L, index)) {
-	case LUA_TNUMBER:
-	case LUA_TCDATA:
-	case LUA_TSTRING:
-		return 1;
-	case LUA_TUSERDATA:
-	{
-		struct tuple *t = lua_istuple(L, index);
-		if (t == NULL)
-			luaL_error(L, "box.pack: unsupported type");
-		return t->field_count;
-	}
-	case LUA_TTABLE:
-	{
-		if (level >= BOX_PACK_MAXNESTING)
-			return 0; /* Limit nested tables */
-
-		int size = 0;
-		lua_pushnil(L);
-		while (lua_next(L, index) != 0) {
-			/* Sic: use absolute index. */
-			size += luaL_packsize_r(L, lua_gettop(L), level++);
-			lua_pop(L, 1);
-		}
-		return size;
-	}
-	default:
-		luaL_error(L, "box.pack: unsupported type");
-	}
-	return 0;
-}
-
-static int
-luaL_packsize(struct lua_State *L, int index)
-{
-	return luaL_packsize_r(L, index, 0);
-}
-
-
-/*
- * This function is recursive. \a level param is needed to control
- * the maximum recursion level.
- */
-static void
-luaL_packvalue_r(struct lua_State *L, struct tbuf *b, int index, int level)
-{
-	struct lua_field field;
-	lua_tofield(L, index, &field);
-	if (field.type != UNKNOWN) {
-		tbuf_ensure(b, field.len + 5);
-		char *data = pack_lstr(b->data + b->size,
-					field.data, field.len);
-		b->size = data - b->data;
-		return;
-	}
-
-	switch (lua_type(L, index)) {
-	case LUA_TUSERDATA:
-	{
-		struct tuple *tuple = lua_istuple(L, index);
-		if (tuple == NULL)
-			luaL_error(L, "box.pack: unsupported type");
-		tuple_to_tbuf(tuple, b);
-		return;
-	}
-	case LUA_TTABLE:
-	{
-		if (level >= BOX_PACK_MAXNESTING)
-			return; /* Limit nested tables */
-		lua_pushnil(L);
-		while (lua_next(L, index) != 0) {
-			/* Sic: use absolute index. */
-			luaL_packvalue_r(L, b, lua_gettop(L), level + 1);
-			lua_pop(L, 1);
-		}
-		return;
-	}
-	default:
-		luaL_error(L, "box.pack: unsupported type");
-		return;
-	}
-}
-
-static void
-luaL_packvalue(struct lua_State *L, struct tbuf *b, int index)
-{
-	return luaL_packvalue_r(L, b, index, 0);
-}
-
-static void
-luaL_packstack(struct lua_State *L, struct tbuf *b, int first, int last)
-{
-	int size = 0;
-	/* sic: if arg_count is 0, first > last */
-	for (int i = first; i <= last; ++i)
-		size += luaL_packsize(L, i);
-
-	tbuf_ensure(b, size + sizeof(size));
-	tbuf_append(b, (char *) &size, sizeof(size));
-	for (int i = first; i <= last; ++i)
-		luaL_packvalue(L, b, i);
-}
-
-
-/**
- * To use Tarantool/Box binary protocol primitives from Lua, we
- * need a way to pack Lua variables into a binary representation.
- * We do it by exporting a helper function
- *
- * box.pack(format, args...)
- *
- * which takes the format, which is very similar to Perl 'pack'
- * format, and a list of arguments, and returns a binary string
- * which has the arguments packed according to the format.
- *
- * For example, a typical SELECT packet packs in Lua like this:
- *
- * pkt = box.pack("iiiiiip", -- pack format
- *                         0, -- space id
- *                         0, -- index id
- *                         0, -- offset
- *                         2^32, -- limit
- *                         1, -- number of SELECT arguments
- *                         1, -- tuple cardinality
- *                         key); -- the key to use for SELECT
- *
- * @sa doc/box-protocol.txt, binary protocol description
- * @todo: implement box.unpack(format, str), for testing purposes
- */
-static int
-lbox_pack(struct lua_State *L)
-{
-	const char *format = luaL_checkstring(L, 1);
-	/* first arg comes second */
-	int i = 2;
-	int nargs = lua_gettop(L);
-	size_t size;
-	const char *str;
-
-	PallocGuard palloc_guard(fiber_ptr->gc_pool);
-	struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-
-	struct lua_field field;
-	double dbl;
-	float flt;
-	char *data;
-	while (*format) {
-		if (i > nargs)
-			luaL_error(L, "box.pack: argument count does not match "
-				   "the format");
-		lua_tofield(L, i, &field);
-		switch (*format) {
-		case 'B':
-		case 'b':
-			/* signed and unsigned 8-bit integers */
-			if (field.type != NUM || field.u32 > UINT8_MAX)
-				luaL_error(L, "box.pack: expected 8-bit int");
-			tbuf_append(b, (char *) &field.u32, sizeof(uint8_t));
-			break;
-		case 'S':
-		case 's':
-			/* signed and unsigned 16-bit integers */
-			if (field.type != NUM || field.u32 > UINT16_MAX)
-				luaL_error(L, "box.pack: expected 16-bit int");
-			tbuf_append(b, (char *) &field.u32, sizeof(uint16_t));
-			break;
-		case 'n':
-			/* signed and unsigned 16-bit big endian integers */
-			if (field.type != NUM || field.u32 > UINT16_MAX)
-				luaL_error(L, "box.pack: expected 16-bit int");
-			field.u32 = (uint16_t) htons((uint16_t) field.u32);
-			tbuf_append(b, (char *) &field.u32, sizeof(uint16_t));
-			break;
-		case 'I':
-		case 'i':
-			/* signed and unsigned 32-bit integers */
-			if (field.type != NUM)
-				luaL_error(L, "box.pack: expected 32-bit int");
-			tbuf_append(b, (char *) &field.u32, sizeof(uint32_t));
-			break;
-		case 'N':
-			/* signed and unsigned 32-bit big endian integers */
-			if (field.type != NUM)
-				luaL_error(L, "box.pack: expected 32-bit int");
-			field.u32 = htonl(field.u32);
-			tbuf_append(b, (char *) &field.u32, sizeof(uint32_t));
-			break;
-		case 'L':
-		case 'l':
-			/* signed and unsigned 64-bit integers */
-			if (field.type == NUM) {
-				/* extend 32-bit value to 64-bit */
-				field.u64 = field.u32;
-			} else if (field.type != NUM64) {
-				luaL_error(L, "box.pack: expected 64-bit int");
-			}
-			tbuf_append(b, (char *) &field.u64, sizeof(uint64_t));
-			break;
-		case 'Q':
-		case 'q':
-			/* signed and unsigned 64-bit integers */
-			if (field.type == NUM) {
-				/* extend 32-bit value to 64-bit */
-				field.u64 = field.u32;
-			} else if (field.type != NUM64){
-				luaL_error(L, "box.pack: expected 64-bit int");
-			}
-			field.u64 = bswap_u64(field.u64);
-			tbuf_append(b, (char *) &field.u64, sizeof(uint64_t));
-			break;
-		case 'd':
-			dbl = (double) lua_tonumber(L, i);
-			tbuf_append(b, (char *) &dbl, sizeof(double));
-			break;
-		case 'f':
-			flt = (float) lua_tonumber(L, i);
-			tbuf_append(b, (char *) &flt, sizeof(float));
-			break;
-		case 'w':
-			/* Perl 'pack' BER-encoded integer */
-			if (field.type != NUM)
-				luaL_error(L, "box.pack: expected 32-bit int");
-
-			tbuf_ensure(b, 5);
-			data = pack_varint32(b->data + b->size, field.u32);
-			assert(data <= b->data + b->capacity);
-			b->size = data - b->data;
-			break;
-		case 'A':
-		case 'a':
-			/* A sequence of bytes */
-			str = luaL_checklstring(L, i, &size);
-			tbuf_append(b, str, size);
-			break;
-		case 'P':
-		case 'p':
-			luaL_packvalue(L, b, i);
-			break;
-		case 'V':
-		{
-			int arg_count = luaL_checkint(L, i);
-			if (i + arg_count > nargs)
-				luaL_error(L, "box.pack: argument count does not match "
-					   "the format");
-			luaL_packstack(L, b, i + 1, i + arg_count);
-			i += arg_count;
-			break;
-		}
-		case '=':
-			/* update tuple set foo = bar */
-		case '+':
-			/* set field += val */
-		case '-':
-			/* set field -= val */
-		case '&':
-			/* set field & =val */
-		case '|':
-			/* set field |= val */
-		case '^':
-			/* set field ^= val */
-		case ':':
-			/* splice */
-		case '#':
-			/* delete field */
-		case '!':
-			/* insert field */
-			/* field no */
-			tbuf_ensure(b, sizeof(uint32_t) + 1);
-			data = b->data + b->size;
-
-			data = pack_u32(data, lua_tointeger(L, i));
-			*data++ = format_to_opcode(*format);
-
-			assert(data <= b->data + b->capacity);
-			b->size = data - b->data;
-			break;
-		default:
-			luaL_error(L, "box.pack: unsupported pack "
-				   "format specifier '%c'", *format);
-		}
-		i++;
-		format++;
-	}
-
-	lua_pushlstring(L, tbuf_str(b), b->size);
-
-	return 1;
-}
-
-const char *
-box_unpack_response(struct lua_State *L, const char *s, const char *end)
-{
-	uint32_t tuple_count = pick_u32(&s, end);
-
-	/* Unpack and push tuples. */
-	while (tuple_count--) {
-		uint32_t bsize = pick_u32(&s, end);
-		uint32_t field_count = pick_u32(&s, end);
-		const char *tend = s + bsize;
-		if (tend > end)
-			tnt_raise(IllegalParams, "incorrect packet length");
-
-		struct tuple *tuple = tuple_new(tuple_format_ber,
-						field_count, &s, tend);
-		lbox_pushtuple(L, tuple);
-	}
-	return s;
-}
-
-
-static int
-lbox_unpack(struct lua_State *L)
-{
-	size_t format_size = 0;
-	const char *format = luaL_checklstring(L, 1, &format_size);
-	const char *f = format;
-
-	size_t str_size = 0;
-	const char *str =  luaL_checklstring(L, 2, &str_size);
-	const char *end = str + str_size;
-	const char *s = str;
-
-	int save_stacksize = lua_gettop(L);
-
-	char charbuf;
-	uint8_t  u8buf;
-	uint16_t u16buf;
-	uint32_t u32buf;
-	double dbl;
-	float flt;
-
-#define CHECK_SIZE(cur) if (unlikely((cur) >= end)) {	                \
-	luaL_error(L, "box.unpack('%c'): got %d bytes (expected: %d+)",	\
-		   *f, (int) (end - str), (int) 1 + ((cur) - str));	\
-}
-	while (*f) {
-		switch (*f) {
-		case 'b':
-			CHECK_SIZE(s);
-			u8buf = *(uint8_t *) s;
-			lua_pushnumber(L, u8buf);
-			s++;
-			break;
-		case 's':
-			CHECK_SIZE(s + 1);
-			u16buf = *(uint16_t *) s;
-			lua_pushnumber(L, u16buf);
-			s += 2;
-			break;
-		case 'n':
-			CHECK_SIZE(s + 1);
-			u16buf = ntohs(*(uint16_t *) s);
-			lua_pushnumber(L, u16buf);
-			s += 2;
-			break;
-		case 'i':
-			CHECK_SIZE(s + 3);
-			u32buf = *(uint32_t *) s;
-			lua_pushnumber(L, u32buf);
-			s += 4;
-			break;
-		case 'N':
-			CHECK_SIZE(s + 3);
-			u32buf = ntohl(*(uint32_t *) s);
-			lua_pushnumber(L, u32buf);
-			s += 4;
-			break;
-		case 'l':
-			CHECK_SIZE(s + 7);
-			luaL_pushnumber64(L, *(uint64_t*) s);
-			s += 8;
-			break;
-		case 'q':
-			CHECK_SIZE(s + 7);
-			luaL_pushnumber64(L, bswap_u64(*(uint64_t*) s));
-			s += 8;
-			break;
-		case 'd':
-			CHECK_SIZE(s + 7);
-			dbl = *(double *) s;
-			lua_pushnumber(L, dbl);
-			s += 8;
-			break;
-		case 'f':
-			CHECK_SIZE(s + 3);
-			flt = *(float *) s;
-			lua_pushnumber(L, flt);
-			s += 4;
-			break;
-		case 'w':
-			/* pick_varint32 throws exception on error. */
-			u32buf = pick_varint32(&s, end);
-			lua_pushnumber(L, u32buf);
-			break;
-
-		case 'a':
-		case 'A': /* The rest of the data is a Lua string. */
-			lua_pushlstring(L, s, end - s);
-			s = end;
-			break;
-		case 'P':
-		case 'p':
-			/* pick_varint32 throws exception on error. */
-			u32buf = pick_varint32(&s, end);
-			CHECK_SIZE(s + u32buf - 1);
-			lua_pushlstring(L, s, u32buf);
-			s += u32buf;
-			break;
-		case '=':
-			/* update tuple set foo = bar */
-		case '+':
-			/* set field += val */
-		case '-':
-			/* set field -= val */
-		case '&':
-			/* set field & =val */
-		case '|':
-			/* set field |= val */
-		case '^':
-			/* set field ^= val */
-		case ':':
-			/* splice */
-		case '#':
-			/* delete field */
-		case '!':
-			/* insert field */
-			CHECK_SIZE(s + 4);
-
-			/* field no */
-			u32buf = *(uint32_t *) s;
-
-			/* opcode */
-			charbuf = *(s + 4);
-			charbuf = opcode_to_format(charbuf);
-			if (charbuf != *f) {
-				luaL_error(L, "box.unpack('%s'): "
-					   "unexpected opcode: "
-					   "offset %d, expected '%c',"
-					   "found '%c'",
-					   format, s - str, *f, charbuf);
-			}
-
-			lua_pushnumber(L, u32buf);
-			s += 5;
-			break;
-
-		case 'R': /* Unpack server response, IPROTO format. */
-		{
-			s = box_unpack_response(L, s, end);
-			break;
-		}
-		default:
-			luaL_error(L, "box.unpack: unsupported "
-				   "format specifier '%c'", *f);
-		}
-		f++;
-	}
-
-	assert(s <= end);
-
-	if (s != end) {
-		luaL_error(L, "box.unpack('%s'): too many bytes: "
-			   "unpacked %d, total %d",
-			   format, s - str, str_size);
-	}
-
-	return lua_gettop(L) - save_stacksize;
-
-#undef CHECK_SIZE
-}
-
-static const struct luaL_reg boxlib[] = {
-	{"process", lbox_process},
-	{"call_loadproc",  lbox_call_loadproc},
-	{"raise", lbox_raise},
-	{"pack", lbox_pack},
-	{"unpack", lbox_unpack},
-	{NULL, NULL}
-};
-
-void
-mod_lua_init(struct lua_State *L)
-{
-	/* box, box.tuple */
-	tarantool_lua_register_type(L, tuplelib_name, lbox_tuple_meta);
-	luaL_register(L, tuplelib_name, lbox_tuplelib);
-	lua_pop(L, 1);
-	tarantool_lua_register_type(L, tuple_iteratorlib_name,
-				    lbox_tuple_iterator_meta);
-	luaL_register(L, "box", boxlib);
-	lua_pop(L, 1);
-	/* box.index */
-	tarantool_lua_register_type(L, indexlib_name, lbox_index_meta);
-	luaL_register(L, "box.index", indexlib);
-	box_index_init_iterator_types(L, -2);
-	lua_pop(L, 1);
-	tarantool_lua_register_type(L, iteratorlib_name, lbox_iterator_meta);
-
-	/* Load Lua extension */
-	for (const char **s = lua_sources; *s; s++) {
-		if (luaL_dostring(L, *s))
-			panic("Error loading Lua source %.160s...: %s",
-			      *s, lua_tostring(L, -1));
-	}
-
-	assert(lua_gettop(L) == 0);
-
-	root_L = L;
-}
diff --git a/src/iproto.cc b/src/iproto.cc
deleted file mode 100644
index 81eec8464139c6c650935b7b619c4cda23627763..0000000000000000000000000000000000000000
--- a/src/iproto.cc
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "iproto.h"
-#include <string.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "iproto_port.h"
-#include "tarantool.h"
-#include "exception.h"
-#include "errcode.h"
-#include "fiber.h"
-#include "say.h"
-#include "evio.h"
-#include "session.h"
-#include "scoped_guard.h"
-
-static struct iproto_header dummy_header = { 0, 0, 0 };
-const uint32_t msg_ping = 0xff00;
-
-/* {{{ iproto_queue */
-
-struct iproto_request;
-
-/**
- * Implementation of an input queue of the box request processor.
- *
- * Socket event handlers read data, determine request boundaries
- * and enqueue requests. Once all input/output events are
- * processed, an own event handler is invoked to deal with the
- * requests in the queue: it's important that each request is
- * processed in a fiber environment.
- *
- * @sa iproto_queue_schedule, iproto_handler, iproto_handshake
- */
-
-struct iproto_queue
-{
-	/**
-	 * Ring buffer of fixed size, preallocated
-	 * during initialization.
-	 */
-	struct iproto_request *queue;
-	/**
-	 * Main function of the fiber invoked to handle
-	 * all outstanding tasks in this queue.
-	 */
-	void (*handler)(va_list);
-	/**
-	 * Cache of fibers which work on requests
-	 * in this queue.
-	 */
-	struct rlist fiber_cache;
-	/**
-	 * Used to trigger request processing when
-	 * the queue becomes non-empty.
-	 */
-	struct ev_async watcher;
-	/* Ring buffer position. */
-	int begin, end;
-	/* Ring buffer size. */
-	int size;
-};
-
-enum {
-	IPROTO_REQUEST_QUEUE_SIZE = 2048,
-};
-
-struct iproto_session;
-
-typedef void (*iproto_request_f)(struct iproto_request *);
-
-/**
- * A single request from the client. All requests
- * from all clients are queued into a single queue
- * and processed in FIFO order.
- */
-struct iproto_request
-{
-	struct iproto_session *session;
-	struct iobuf *iobuf;
-	/* Position of the request in the input buffer. */
-	struct iproto_header *header;
-	iproto_request_f process;
-};
-
-/**
- * A single global queue for all requests in all connections. All
- * requests are processed concurrently.
- * Is also used as a queue for just established connections and to
- * execute disconnect triggers. A few notes about these triggers:
- * - they need to be run in a fiber
- * - unlike an ordinary request failure, on_connect trigger
- *   failure must lead to connection shutdown.
- * - as long as on_connect trigger can be used for client
- *   authentication, it must be processed before any other request
- *   on this connection.
- */
-static struct iproto_queue request_queue;
-
-static inline bool
-iproto_queue_is_empty(struct iproto_queue *i_queue)
-{
-	return i_queue->begin == i_queue->end;
-}
-
-static inline void
-iproto_enqueue_request(struct iproto_queue *i_queue,
-		       struct iproto_session *session,
-		       struct iobuf *iobuf,
-		       struct iproto_header *header,
-		       iproto_request_f process)
-{
-	/* If the queue is full, invoke the handler to work it off. */
-	if (i_queue->end == i_queue->size)
-		ev_invoke(&i_queue->watcher, EV_CUSTOM);
-	assert(i_queue->end < i_queue->size);
-	bool was_empty = iproto_queue_is_empty(i_queue);
-	struct iproto_request *request = i_queue->queue + i_queue->end++;
-
-	request->session = session;
-	request->iobuf = iobuf;
-	request->header = header;
-	request->process = process;
-	/*
-	 * There were some queued requests, ensure they are
-	 * handled.
-	 */
-	if (was_empty)
-		ev_feed_event(&request_queue.watcher, EV_CUSTOM);
-}
-
-static inline bool
-iproto_dequeue_request(struct iproto_queue *i_queue,
-		       struct iproto_request *out)
-{
-	if (i_queue->begin == i_queue->end)
-		return false;
-	struct iproto_request *request = i_queue->queue + i_queue->begin++;
-	if (i_queue->begin == i_queue->end)
-		i_queue->begin = i_queue->end = 0;
-	*out = *request;
-	return true;
-}
-
-/** Put the current fiber into a queue fiber cache. */
-static inline void
-iproto_cache_fiber(struct iproto_queue *i_queue)
-{
-	fiber_gc();
-	rlist_add_entry(&i_queue->fiber_cache, fiber_ptr, state);
-	fiber_yield();
-}
-
-/** Create fibers to handle all outstanding tasks. */
-static void
-iproto_queue_schedule(struct ev_async *watcher,
-		      int events __attribute__((unused)))
-{
-	struct iproto_queue *i_queue = (struct iproto_queue *) watcher->data;
-	while (! iproto_queue_is_empty(i_queue)) {
-
-		struct fiber *f;
-		if (! rlist_empty(&i_queue->fiber_cache))
-			f = rlist_shift_entry(&i_queue->fiber_cache,
-					      struct fiber, state);
-		else
-			f = fiber_new("iproto", i_queue->handler);
-		fiber_call(f, i_queue);
-	}
-}
-
-static inline void
-iproto_queue_init(struct iproto_queue *i_queue,
-		  int size, void (*handler)(va_list))
-{
-	i_queue->size = size;
-	i_queue->begin = i_queue->end = 0;
-	i_queue->queue = (struct iproto_request *) palloc(eter_pool, size *
-				sizeof (struct iproto_request));
-	/**
-	 * Initialize an ev_async event which would start
-	 * workers for all outstanding tasks.
-	 */
-	ev_async_init(&i_queue->watcher, iproto_queue_schedule);
-	i_queue->watcher.data = i_queue;
-	i_queue->handler = handler;
-	rlist_create(&i_queue->fiber_cache);
-}
-
-static inline uint32_t
-iproto_session_id(struct iproto_session *session);
-
-static inline uint64_t
-iproto_session_cookie(struct iproto_session *session);
-
-/** A handler to process all queued requests. */
-static void
-iproto_queue_handler(va_list ap)
-{
-	struct iproto_queue *i_queue = va_arg(ap, struct iproto_queue *);
-	struct iproto_request request;
-restart:
-	while (iproto_dequeue_request(i_queue, &request)) {
-
-		fiber_set_sid(fiber_ptr, iproto_session_id(request.session), iproto_session_cookie(request.session));
-		request.process(&request);
-	}
-	iproto_cache_fiber(&request_queue);
-	goto restart;
-}
-
-/* }}} */
-
-/* {{{ iproto_session */
-
-/** Context of a single client connection. */
-struct iproto_session
-{
-	/* Cache of iproto_session objects. */
-	SLIST_ENTRY(iproto_session) next_in_cache;
-	/**
-	 * Two rotating buffers for I/O. Input is always read into
-	 * iobuf[0]. As soon as iobuf[0] input buffer becomes full,
-	 * iobuf[0] is moved to iobuf[1], for flushing. As soon as
-	 * all output in iobuf[1].out is sent to the client, iobuf[1]
-	 * and iobuf[0] are moved around again.
-	 */
-	struct iobuf *iobuf[2];
-	/*
-	 * Size of readahead which is not parsed yet, i.e.
-	 * size of a piece of request which is not fully read.
-	 * Is always relative to iobuf[0]->in.end. In other words,
-	 * iobuf[0]->in.end - parse_size gives the start of the
-	 * unparsed request. A size rather than a pointer is used
-	 * to be safe in case in->buf is reallocated. Being
-	 * relative to in->end, rather than to in->pos is helpful to
-	 * make sure ibuf_reserve() or iobuf rotation don't make
-	 * the value meaningless.
-	 */
-	ssize_t parse_size;
-	/** Current write position in the output buffer */
-	struct obuf_svp write_pos;
-	/**
-	 * Function of the request processor to handle
-	 * a single request.
-	 */
-	box_process_func *handler;
-	struct ev_io input;
-	struct ev_io output;
-	/** Session id. */
-	uint32_t sid;
-	uint64_t cookie;
-};
-
-SLIST_HEAD(, iproto_session) iproto_session_cache =
-	SLIST_HEAD_INITIALIZER(iproto_session_cache);
-
-/**
- * A session is idle when the client is gone
- * and there are no outstanding requests in the request queue.
- * An idle session can be safely garbage collected.
- * Note: a session only becomes idle after iproto_session_shutdown(),
- * which closes the fd.  This is why here the check is for
- * evio_is_active() (false if fd is closed), not ev_is_active()
- * (false if event is not started).
- */
-static inline bool
-iproto_session_is_idle(struct iproto_session *session)
-{
-	return !evio_is_active(&session->input) &&
-		ibuf_size(&session->iobuf[0]->in) == 0 &&
-		ibuf_size(&session->iobuf[1]->in) == 0;
-}
-
-static inline uint32_t
-iproto_session_id(struct iproto_session *session)
-{
-	return session->sid;
-}
-
-static inline uint64_t
-iproto_session_cookie(struct iproto_session *session)
-{
-	return session->cookie;
-}
-
-static void
-iproto_session_on_input(struct ev_io *watcher,
-			int revents __attribute__((unused)));
-static void
-iproto_session_on_output(struct ev_io *watcher,
-			 int revents __attribute__((unused)));
-
-static void
-iproto_process_request(struct iproto_request *request);
-
-static void
-iproto_process_connect(struct iproto_request *request);
-
-static void
-iproto_process_disconnect(struct iproto_request *request);
-
-static struct iproto_session *
-iproto_session_create(const char *name, int fd, struct sockaddr_in *addr,
-		      box_process_func *param)
-{
-	struct iproto_session *session;
-	if (SLIST_EMPTY(&iproto_session_cache)) {
-		session = (struct iproto_session *) palloc(eter_pool, sizeof(*session));
-		session->input.data = session->output.data = session;
-	} else {
-		session = SLIST_FIRST(&iproto_session_cache);
-		SLIST_REMOVE_HEAD(&iproto_session_cache, next_in_cache);
-		assert(session->input.fd == -1);
-		assert(session->output.fd == -1);
-	}
-	session->handler = param;
-	ev_io_init(&session->input, iproto_session_on_input, fd, EV_READ);
-	ev_io_init(&session->output, iproto_session_on_output, fd, EV_WRITE);
-	session->iobuf[0] = iobuf_new(name);
-	session->iobuf[1] = iobuf_new(name);
-	session->parse_size = 0;
-	session->write_pos = obuf_create_svp(&session->iobuf[0]->out);
-	session->sid = 0;
-	session->cookie = *(uint64_t *) addr;
-	return session;
-}
-
-/** Recycle a session. Never throws. */
-static inline void
-iproto_session_destroy(struct iproto_session *session)
-{
-	assert(iproto_session_is_idle(session));
-	assert(!evio_is_active(&session->output));
-	session_destroy(session->sid); /* Never throws. No-op if sid is 0. */
-	iobuf_delete(session->iobuf[0]);
-	iobuf_delete(session->iobuf[1]);
-	SLIST_INSERT_HEAD(&iproto_session_cache, session, next_in_cache);
-}
-
-static inline void
-iproto_session_shutdown(struct iproto_session *session)
-{
-	ev_io_stop(&session->input);
-	ev_io_stop(&session->output);
-	close(session->input.fd);
-	session->input.fd = session->output.fd = -1;
-	/*
-	 * Discard unparsed data, to recycle the session
-	 * as soon as all parsed data is processed.
-	 */
-	session->iobuf[0]->in.end -= session->parse_size;
-	/*
-	 * If the session is not idle, it is destroyed
-	 * after the last request is handled. Otherwise,
-	 * queue a separate request to run on_disconnect()
-	 * trigger and destroy the session.
-	 * Sic: the check is mandatory to not destroy a session
-	 * twice.
-	 */
-	if (iproto_session_is_idle(session)) {
-		iproto_enqueue_request(&request_queue, session,
-				       session->iobuf[0], &dummy_header,
-				       iproto_process_disconnect);
-	}
-}
-
-static inline void
-iproto_validate_header(struct iproto_header *header, int fd)
-{
-	(void) fd;
-	if (header->len > IPROTO_BODY_LEN_MAX) {
-		/*
-		 * The package is too big, just close connection for now to
-		 * avoid DoS.
-		 */
-		tnt_raise(IllegalParams, "received package is too big");
-	}
-}
-
-/**
- * If there is no space for reading input, we can do one of the
- * following:
- * - try to get a new iobuf, so that it can fit the request.
- *   Always getting a new input buffer when there is no space
- *   makes the server susceptible to input-flood attacks.
- *   Therefore, at most 2 iobufs are used in a single session,
- *   one is "open", receiving input, and the  other is closed,
- *   flushing output.
- * - stop input and wait until the client reads piled up output,
- *   so the input buffer can be reused. This complements
- *   the previous strategy. It is only safe to stop input if it
- *   is known that there is output. In this case input event
- *   flow will be resumed when all replies to previous requests
- *   are sent, in iproto_session_gc_iobuf(). Since there are two
- *   buffers, the input is only stopped when both of them
- *   are fully used up.
- *
- * To make this strategy work, each iobuf in use must fit at
- * least one request. Otherwise, iobuf[1] may end
- * up having no data to flush, while iobuf[0] is too small to
- * fit a big incoming request.
- */
-static struct iobuf *
-iproto_session_input_iobuf(struct iproto_session *session)
-{
-	struct iobuf *oldbuf = session->iobuf[0];
-
-	ssize_t to_read = sizeof(struct iproto_header) +
-		(session->parse_size >= sizeof(struct iproto_header) ?
-		iproto(oldbuf->in.end - session->parse_size)->len : 0) -
-		session->parse_size;
-
-	if (ibuf_unused(&oldbuf->in) >= to_read)
-		return oldbuf;
-
-	/** All requests are processed, reuse the buffer. */
-	if (ibuf_size(&oldbuf->in) == session->parse_size) {
-		ibuf_reserve(&oldbuf->in, to_read);
-		return oldbuf;
-	}
-
-	if (! iobuf_is_idle(session->iobuf[1])) {
-		/*
-		 * Wait until the second buffer is flushed
-		 * and becomes available for reuse.
-		 */
-		return NULL;
-	}
-	struct iobuf *newbuf = session->iobuf[1];
-
-	ibuf_reserve(&newbuf->in, to_read + session->parse_size);
-	/*
-	 * Discard unparsed data in the old buffer, otherwise it
-	 * won't be recycled when all parsed requests are processed.
-	 */
-	oldbuf->in.end -= session->parse_size;
-	/* Move the cached request prefix to the new buffer. */
-	memcpy(newbuf->in.pos, oldbuf->in.end, session->parse_size);
-	newbuf->in.end += session->parse_size;
-	/*
-	 * Rotate buffers. Not strictly necessary, but
-	 * helps preserve response order.
-	 */
-	session->iobuf[1] = oldbuf;
-	session->iobuf[0] = newbuf;
-	return newbuf;
-}
-
-/** Enqueue all requests which were read up. */
-static inline void
-iproto_enqueue_batch(struct iproto_session *session, struct ibuf *in, int fd)
-{
-	int batch_size;
-	for (batch_size = 0; ; batch_size++) {
-
-		if (session->parse_size < sizeof(struct iproto_header))
-			break;
-
-		struct iproto_header *
-			header = iproto(in->end - session->parse_size);
-		iproto_validate_header(header, fd);
-
-		if (session->parse_size < (sizeof(struct iproto_header) +
-					   header->len))
-			break;
-
-		iproto_enqueue_request(&request_queue, session,
-				       session->iobuf[0], header,
-				       iproto_process_request);
-		session->parse_size -= sizeof(*header) + header->len;
-	}
-}
-
-static void
-iproto_session_on_input(struct ev_io *watcher,
-			int revents __attribute__((unused)))
-{
-	struct iproto_session *session = (struct iproto_session *) watcher->data;
-	int fd = session->input.fd;
-	assert(fd >= 0);
-
-	try {
-		/* Ensure we have sufficient space for the next round.  */
-		struct iobuf *iobuf = iproto_session_input_iobuf(session);
-		if (iobuf == NULL) {
-			ev_io_stop(&session->input);
-			return;
-		}
-
-		struct ibuf *in = &iobuf->in;
-		/* Read input. */
-		int nrd = sio_read(fd, in->end, ibuf_unused(in));
-		if (nrd < 0) {                  /* Socket is not ready. */
-			ev_io_start(&session->input);
-			return;
-		}
-		if (nrd == 0) {                 /* EOF */
-			iproto_session_shutdown(session);
-			return;
-		}
-		/* Update the read position and session state. */
-		in->end += nrd;
-		session->parse_size += nrd;
-		/* Enqueue all requests which are fully read up. */
-		iproto_enqueue_batch(session, in, fd);
-		/*
-		 * Keep reading input, as long as the socket
-		 * supplies data.
-		 */
-		if (!ev_is_active(&session->input))
-			ev_feed_event(&session->input, EV_READ);
-	} catch (const Exception& e) {
-		e.log();
-		iproto_session_shutdown(session);
-	}
-}
-
-/** Get the iobuf which is currently being flushed. */
-static inline struct iobuf *
-iproto_session_output_iobuf(struct iproto_session *session)
-{
-	if (obuf_size(&session->iobuf[1]->out))
-		return session->iobuf[1];
-	/*
-	 * Don't try to write from a newer buffer if an older one
-	 * exists: in case of a partial write of a newer buffer,
-	 * the client may end up getting a salad of different
-	 * pieces of replies from both buffers.
-	 */
-	if (ibuf_size(&session->iobuf[1]->in) == 0 &&
-	    obuf_size(&session->iobuf[0]->out))
-		return session->iobuf[0];
-	return NULL;
-}
-
-/** writev() to the socket and handle the output. */
-static int
-iproto_flush(struct iobuf *iobuf, int fd, struct obuf_svp *svp)
-{
-	/* Begin writing from the saved position. */
-	struct iovec *iov = iobuf->out.iov + svp->pos;
-	int iovcnt = obuf_iovcnt(&iobuf->out) - svp->pos;
-	assert(iovcnt);
-	ssize_t nwr;
-	try {
-		sio_add_to_iov(iov, -svp->iov_len);
-		nwr = sio_writev(fd, iov, iovcnt);
-
-		sio_add_to_iov(iov, svp->iov_len);
-	} catch (const Exception&) {
-		sio_add_to_iov(iov, svp->iov_len);
-		throw;
-	}
-
-	if (nwr > 0) {
-		if (svp->size + nwr == obuf_size(&iobuf->out)) {
-			iobuf_gc(iobuf);
-			*svp = obuf_create_svp(&iobuf->out);
-			return 0;
-		}
-		svp->size += nwr;
-		svp->pos += sio_move_iov(iov, nwr, &svp->iov_len);
-	}
-	return -1;
-}
-
-static void
-iproto_session_on_output(struct ev_io *watcher,
-			 int revent __attribute__((unused)))
-{
-	struct iproto_session *session = (struct iproto_session *) watcher->data;
-	int fd = session->output.fd;
-	struct obuf_svp *svp = &session->write_pos;
-
-	try {
-		struct iobuf *iobuf;
-		while ((iobuf = iproto_session_output_iobuf(session))) {
-			if (iproto_flush(iobuf, fd, svp) < 0) {
-				ev_io_start(&session->output);
-				return;
-			}
-			if (! ev_is_active(&session->input))
-				ev_feed_event(&session->input, EV_READ);
-		}
-		if (ev_is_active(&session->output))
-			ev_io_stop(&session->output);
-	} catch (const Exception& e) {
-		e.log();
-		iproto_session_shutdown(session);
-	}
-}
-
-/* }}} */
-
-/* {{{ iproto_process_* functions */
-
-/** Stack reply to 'ping' packet. */
-static inline void
-iproto_reply_ping(struct obuf *out, struct iproto_header *req)
-{
-	struct iproto_header reply = *req;
-	reply.len = 0;
-	obuf_dup(out, &reply, sizeof(reply));
-}
-
-/** Send an error packet back. */
-static inline void
-iproto_reply_error(struct obuf *out, struct iproto_header *req,
-		   const ClientError& e)
-{
-	struct iproto_header reply = *req;
-	int errmsg_len = strlen(e.errmsg()) + 1;
-	uint32_t ret_code = tnt_errcode_val(e.errcode());
-	reply.len = sizeof(ret_code) + errmsg_len;;
-	obuf_dup(out, &reply, sizeof(reply));
-	obuf_dup(out, &ret_code, sizeof(ret_code));
-	obuf_dup(out, e.errmsg(), errmsg_len);
-}
-
-/** Stack a reply to a single request to the fiber's io vector. */
-static inline void
-iproto_reply(struct iproto_port *port, box_process_func callback,
-	     struct obuf *out, struct iproto_header *header)
-{
-	if (header->msg_code == msg_ping)
-		return iproto_reply_ping(out, header);
-
-	/* Make request body point to iproto data */
-	char *body = (char *) &header[1];
-	iproto_port_init(port, out, header);
-	try {
-		callback((struct port *) port, header->msg_code,
-			 body, header->len);
-	} catch (const ClientError& e) {
-		if (port->reply.found)
-			obuf_rollback_to_svp(out, &port->svp);
-		iproto_reply_error(out, header, e);
-	}
-}
-
-static void
-iproto_process_request(struct iproto_request *request)
-{
-	struct iproto_session *session = request->session;
-	struct iproto_header *header = request->header;
-	struct iobuf *iobuf = request->iobuf;
-	struct iproto_port port;
-
-	auto scope_guard = make_scoped_guard([=]{
-		iobuf->in.pos += sizeof(*header) + header->len;
-		if (iproto_session_is_idle(session))
-			iproto_session_destroy(session);
-	});
-
-	if (unlikely(! evio_is_active(&session->output)))
-		return;
-
-	iproto_reply(&port, *session->handler, &iobuf->out, header);
-
-	if (unlikely(! evio_is_active(&session->output)))
-		return;
-
-	if (! ev_is_active(&session->output))
-		ev_feed_event(&session->output, EV_WRITE);
-}
-
-/**
- * Handshake a connection: invoke the on-connect trigger
- * and possibly authenticate. Try to send the client an error
- * upon a failure.
- */
-static void
-iproto_process_connect(struct iproto_request *request)
-{
-	struct iproto_session *session = request->session;
-	struct iobuf *iobuf = request->iobuf;
-	int fd = session->input.fd;
-	try {              /* connect. */
-		session->sid = session_create(fd, session->cookie);
-	} catch (const ClientError& e) {
-		iproto_reply_error(&iobuf->out, request->header, e);
-		try {
-			iproto_flush(iobuf, fd, &session->write_pos);
-		} catch (const Exception& e) {
-			e.log();
-		}
-		iproto_session_shutdown(session);
-		return;
-	} catch (const Exception& e) {
-		e.log();
-		assert(session->sid == 0);
-		iproto_session_shutdown(session);
-		return;
-	}
-	/*
-	 * Connect is synchronous, so no one could have been
-	 * messing up with the session while it was in
-	 * progress.
-	 */
-	assert(evio_is_active(&session->input));
-	/* Handshake OK, start reading input. */
-	ev_feed_event(&session->input, EV_READ);
-}
-
-static void
-iproto_process_disconnect(struct iproto_request *request)
-{
-	fiber_set_sid(fiber_ptr, request->session->sid, request->session->cookie);
-	/* Runs the trigger, which may yield. */
-	iproto_session_destroy(request->session);
-}
-
-/** }}} */
-
-/**
- * Create a session context and start input.
- */
-static void
-iproto_on_accept(struct evio_service *service, int fd,
-		 struct sockaddr_in *addr)
-{
-	char name[SERVICE_NAME_MAXLEN];
-	snprintf(name, sizeof(name), "%s/%s", "iobuf", sio_strfaddr(addr));
-
-	struct iproto_session *session;
-
-	box_process_func *process_fun =
-		(box_process_func*) service->on_accept_param;
-	session = iproto_session_create(name, fd, addr, process_fun);
-	iproto_enqueue_request(&request_queue, session,
-			       session->iobuf[0], &dummy_header,
-			       iproto_process_connect);
-}
-
-/**
- * Initialize read-write and read-only ports
- * with binary protocol handlers.
- */
-void
-iproto_init(const char *bind_ipaddr, int primary_port,
-	    int secondary_port)
-{
-	/* Run a primary server. */
-	if (primary_port != 0) {
-		static struct evio_service primary;
-		evio_service_init(&primary, "primary",
-				  bind_ipaddr, primary_port,
-				  iproto_on_accept, &box_process);
-		evio_service_on_bind(&primary,
-				     box_leave_local_standby_mode, NULL);
-		evio_service_start(&primary);
-	}
-
-	/* Run a secondary server. */
-	if (secondary_port != 0) {
-		static struct evio_service secondary;
-		evio_service_init(&secondary, "secondary",
-				  bind_ipaddr, secondary_port,
-				  iproto_on_accept, &box_process_ro);
-		evio_service_start(&secondary);
-	}
-	iproto_queue_init(&request_queue, IPROTO_REQUEST_QUEUE_SIZE,
-			  iproto_queue_handler);
-}
-
diff --git a/src/log_io.cc b/src/log_io.cc
deleted file mode 100644
index 5935af0759d2f35e5a16488dcaf176845735bdb5..0000000000000000000000000000000000000000
--- a/src/log_io.cc
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "log_io.h"
-#include <dirent.h>
-#include <fcntl.h>
-
-#include "palloc.h"
-#include "fiber.h"
-#include "crc32.h"
-#include "fio.h"
-#include "tarantool_eio.h"
-#include "fiob.h"
-
-const uint32_t default_version = 11;
-const log_magic_t row_marker_v11 = 0xba0babed;
-const log_magic_t eof_marker_v11 = 0x10adab1e;
-const char inprogress_suffix[] = ".inprogress";
-const char v11[] = "0.11\n";
-
-void
-header_v11_sign(struct header_v11 *header)
-{
-	header->data_crc32c = crc32_calc(0, (const unsigned char *) header + sizeof(struct
-						  header_v11), header->len);
-	header->header_crc32c = crc32_calc(0, (const unsigned char *) &header->lsn,
-					   sizeof(struct header_v11) -
-					   sizeof(header->header_crc32c));
-}
-
-void
-row_v11_fill(struct row_v11 *row, int64_t lsn, uint16_t tag, uint64_t cookie,
-	     const char *metadata, size_t metadata_len, const char
-	     *data, size_t data_len)
-{
-	row->marker = row_marker_v11;
-	row->tag  = tag;
-	row->cookie = cookie;
-	memcpy(row->data, metadata, metadata_len);
-	memcpy(row->data + metadata_len, data, data_len);
-	header_v11_fill(&row->header, lsn, metadata_len + data_len +
-			sizeof(row->tag) + sizeof(row->cookie));
-}
-
-struct log_dir snap_dir = {
-	/* .panic_if_error = */ false,
-	/* .sync_is_async = */ false,
-	/* .open_wflags = */ "wxd",
-	/* .filetype = */ "SNAP\n",
-	/* .filename_ext = */ ".snap",
-	/* .dirname = */ NULL
-};
-
-struct log_dir wal_dir = {
-	/* .panic_if_error = */ false,
-	/* .sync_is_async = */ true,
-	/* .open_wflags = */ "wx",
-	/* .filetype = */ "XLOG\n",
-	/* .filename_ext = */ ".xlog",
-	/* .dirname = */ NULL
-};
-
-static int
-cmp_i64(const void *_a, const void *_b)
-{
-	const int64_t *a = (const int64_t *) _a, *b = (const int64_t *) _b;
-	if (*a == *b)
-		return 0;
-	return (*a > *b) ? 1 : -1;
-}
-
-static ssize_t
-scan_dir(struct log_dir *dir, int64_t **ret_lsn)
-{
-	ssize_t result = -1;
-	size_t i = 0, size = 1024;
-	ssize_t ext_len = strlen(dir->filename_ext);
-	int64_t *lsn = (int64_t *) palloc(fiber_ptr->gc_pool, sizeof(int64_t) * size);
-	DIR *dh = opendir(dir->dirname);
-
-	if (lsn == NULL || dh == NULL)
-		goto out;
-
-	errno = 0;
-	struct dirent *dent;
-	while ((dent = readdir(dh)) != NULL) {
-
-		char *ext = strchr(dent->d_name, '.');
-		if (ext == NULL)
-		continue;
-
-		const char *suffix = strchr(ext + 1, '.');
-		/*
-		 * A valid ending is either .xlog or
-		 * .xlog.inprogress, given dir->filename_ext ==
-		 * 'xlog'.
-		 */
-		bool ext_is_ok;
-		if (suffix == NULL)
-			ext_is_ok = strcmp(ext, dir->filename_ext) == 0;
-		else
-			ext_is_ok = (strncmp(ext, dir->filename_ext,
-					     ext_len) == 0 &&
-				     strcmp(suffix, inprogress_suffix) == 0);
-		if (!ext_is_ok)
-			continue;
-
-		lsn[i] = strtoll(dent->d_name, &ext, 10);
-		if (strncmp(ext, dir->filename_ext, ext_len) != 0) {
-			/* d_name doesn't parse entirely, ignore it */
-			say_warn("can't parse `%s', skipping", dent->d_name);
-			continue;
-		}
-
-		if (lsn[i] == LLONG_MAX || lsn[i] == LLONG_MIN) {
-			say_warn("can't parse `%s', skipping", dent->d_name);
-			continue;
-		}
-
-		i++;
-		if (i == size) {
-			int64_t *n = (int64_t *) palloc(fiber_ptr->gc_pool, sizeof(int64_t) * size * 2);
-			if (n == NULL)
-				goto out;
-			memcpy(n, lsn, sizeof(int64_t) * size);
-			lsn = n;
-			size = size * 2;
-		}
-	}
-
-	qsort(lsn, i, sizeof(int64_t), cmp_i64);
-
-	*ret_lsn = lsn;
-	result = i;
-out:
-	if (errno != 0)
-		say_syserror("error reading directory `%s'", dir->dirname);
-
-	if (dh != NULL)
-		closedir(dh);
-	return result;
-}
-
-int64_t
-greatest_lsn(struct log_dir *dir)
-{
-	int64_t *lsn;
-	ssize_t count = scan_dir(dir, &lsn);
-
-	if (count <= 0)
-		return count;
-
-	return lsn[count - 1];
-}
-
-int64_t
-find_including_file(struct log_dir *dir, int64_t target_lsn)
-{
-	int64_t *lsn;
-	ssize_t count = scan_dir(dir, &lsn);
-
-	if (count <= 0)
-		return count;
-
-	while (count > 1) {
-		if (*lsn <= target_lsn && target_lsn < *(lsn + 1)) {
-			goto out;
-			return *lsn;
-		}
-		lsn++;
-		count--;
-	}
-
-	/*
-	 * we can't check here for sure will or will not last file
-	 * contain record with desired lsn since number of rows in file
-	 * is not known beforehand. so, we simply return the last one.
-	 */
-
-      out:
-	return *lsn;
-}
-
-char *
-format_filename(struct log_dir *dir, int64_t lsn, enum log_suffix suffix)
-{
-	static __thread char filename[PATH_MAX + 1];
-	const char *suffix_str = suffix == INPROGRESS ? inprogress_suffix : "";
-	snprintf(filename, PATH_MAX, "%s/%020lld%s%s",
-		 dir->dirname, (long long)lsn, dir->filename_ext, suffix_str);
-	return filename;
-}
-
-/* }}} */
-
-/* {{{ struct log_io_cursor */
-
-static const char ROW_EOF[] = "";
-
-const char *
-row_reader_v11(FILE *f, uint32_t *rowlen)
-{
-	struct header_v11 m;
-
-	uint32_t header_crc, data_crc;
-
-	if (fread(&m, sizeof(m), 1, f) != 1)
-		return ROW_EOF;
-
-	/* header crc32c calculated on <lsn, tm, len, data_crc32c> */
-	header_crc = crc32_calc(0, (unsigned char *) &m + offsetof(struct header_v11, lsn),
-				sizeof(m) - offsetof(struct header_v11, lsn));
-
-	if (m.header_crc32c != header_crc) {
-		say_error("header crc32c mismatch");
-		return NULL;
-	}
-	char *row = (char *) palloc(fiber_ptr->gc_pool, sizeof(m) + m.len);
-	memcpy(row, &m, sizeof(m));
-
-	if (fread(row + sizeof(m), m.len, 1, f) != 1)
-		return ROW_EOF;
-
-	data_crc = crc32_calc(0, (unsigned char *) row + sizeof(m), m.len);
-	if (m.data_crc32c != data_crc) {
-		say_error("data crc32c mismatch");
-		return NULL;
-	}
-
-	say_debug("read row v11 success lsn:%lld", (long long) m.lsn);
-	*rowlen = m.len + sizeof(m);
-	return row;
-}
-
-void
-log_io_cursor_open(struct log_io_cursor *i, struct log_io *l)
-{
-	i->log = l;
-	i->row_count = 0;
-	i->good_offset = ftello(l->f);
-	i->eof_read  = false;
-}
-
-void
-log_io_cursor_close(struct log_io_cursor *i)
-{
-	struct log_io *l = i->log;
-	l->rows += i->row_count;
-	/*
-	 * Since we don't close log_io
-	 * we must rewind log_io to last known
-	 * good position if there was an error.
-	 * Seek back to last known good offset.
-	 */
-	fseeko(l->f, i->good_offset, SEEK_SET);
-	prelease(fiber_ptr->gc_pool);
-}
-
-/**
- * Read logfile contents using designated format, panic if
- * the log is corrupted/unreadable.
- *
- * @param i	iterator object, encapsulating log specifics.
- *
- */
-const char *
-log_io_cursor_next(struct log_io_cursor *i, uint32_t *rowlen)
-{
-	struct log_io *l = i->log;
-	const char *row;
-	log_magic_t magic;
-	off_t marker_offset = 0;
-
-	assert(i->eof_read == false);
-
-	say_debug("log_io_cursor_next: marker:0x%016X/%zu",
-		  row_marker_v11, sizeof(row_marker_v11));
-
-	/*
-	 * Don't let gc pool grow too much. Yet to
-	 * it before reading the next row, to make
-	 * sure it's not freed along here.
-	 */
-	prelease_after(fiber_ptr->gc_pool, 128 * 1024);
-
-restart:
-	if (marker_offset > 0)
-		fseeko(l->f, marker_offset + 1, SEEK_SET);
-
-	if (fread(&magic, sizeof(magic), 1, l->f) != 1)
-		goto eof;
-
-	while (magic != row_marker_v11) {
-		int c = fgetc(l->f);
-		if (c == EOF) {
-			say_debug("eof while looking for magic");
-			goto eof;
-		}
-		magic = magic >> 8 |
-			((log_magic_t) c & 0xff) << (sizeof(magic)*8 - 8);
-	}
-	marker_offset = ftello(l->f) - sizeof(row_marker_v11);
-	if (i->good_offset != marker_offset)
-		say_warn("skipped %jd bytes after 0x%08jx offset",
-			(intmax_t)(marker_offset - i->good_offset),
-			(uintmax_t)i->good_offset);
-	say_debug("magic found at 0x%08jx", (uintmax_t)marker_offset);
-
-	row = row_reader_v11(l->f, rowlen);
-	if (row == ROW_EOF)
-		goto eof;
-
-	if (row == NULL) {
-		if (l->dir->panic_if_error)
-			panic("failed to read row");
-		say_warn("failed to read row");
-		goto restart;
-	}
-
-	i->good_offset = ftello(l->f);
-	i->row_count++;
-
-	if (i->row_count % 100000 == 0)
-		say_info("%.1fM rows processed", i->row_count / 1000000.);
-
-	return row;
-eof:
-	/*
-	 * The only two cases of fully read file:
-	 * 1. sizeof(eof_marker) > 0 and it is the last record in file
-	 * 2. sizeof(eof_marker) == 0 and there is no unread data in file
-	 */
-	if (ftello(l->f) == i->good_offset + sizeof(eof_marker_v11)) {
-		fseeko(l->f, i->good_offset, SEEK_SET);
-		if (fread(&magic, sizeof(magic), 1, l->f) != 1) {
-
-			say_error("can't read eof marker");
-		} else if (magic == eof_marker_v11) {
-			i->good_offset = ftello(l->f);
-			i->eof_read = true;
-		} else if (magic != row_marker_v11) {
-			say_error("eof marker is corrupt: %lu",
-				  (unsigned long) magic);
-		} else {
-			/*
-			 * Row marker at the end of a file: a sign
-			 * of a corrupt log file in case of
-			 * recovery, but OK in case we're in local
-			 * hot standby or replication relay mode
-			 * (i.e. data is being written to the
-			 * file. Don't pollute the log, the
-			 * condition is taken care of up the
-			 * stack.
-			 */
-		}
-	}
-	/* No more rows. */
-	return NULL;
-}
-
-/* }}} */
-
-int
-inprogress_log_rename(struct log_io *l)
-{
-	char *filename = l->filename;
-	char new_filename[PATH_MAX];
-	char *suffix = strrchr(filename, '.');
-
-	assert(l->is_inprogress);
-	assert(suffix);
-	assert(strcmp(suffix, inprogress_suffix) == 0);
-
-	/* Create a new filename without '.inprogress' suffix. */
-	memcpy(new_filename, filename, suffix - filename);
-	new_filename[suffix - filename] = '\0';
-
-	if (rename(filename, new_filename) != 0) {
-		say_syserror("can't rename %s to %s", filename, new_filename);
-
-		return -1;
-	}
-	l->is_inprogress = false;
-	return 0;
-}
-
-int
-inprogress_log_unlink(char *filename)
-{
-#ifndef NDEBUG
-	char *suffix = strrchr(filename, '.');
-	assert(suffix);
-	assert(strcmp(suffix, inprogress_suffix) == 0);
-#endif
-	if (unlink(filename) != 0) {
-		/* Don't panic if there is no such file. */
-		if (errno == ENOENT)
-			return 0;
-
-		say_syserror("can't unlink %s", filename);
-
-		return -1;
-	}
-
-	return 0;
-}
-
-/* {{{ struct log_io */
-
-int
-log_io_close(struct log_io **lptr)
-{
-	struct log_io *l = *lptr;
-	int r;
-
-	if (l->mode == LOG_WRITE) {
-		fwrite(&eof_marker_v11, 1, sizeof(log_magic_t), l->f);
-		/*
-		 * Sync the file before closing, since
-		 * otherwise we can end up with a partially
-		 * written file in case of a crash.
-		 * Do not sync if the file is opened with O_SYNC.
-		 */
-		if (! strchr(l->dir->open_wflags, 's'))
-			log_io_sync(l);
-		if (l->is_inprogress && inprogress_log_rename(l) != 0)
-			panic("can't rename 'inprogress' WAL");
-	}
-
-	r = fclose(l->f);
-	if (r < 0)
-		say_syserror("can't close");
-	free(l);
-	*lptr = NULL;
-	return r;
-}
-
-/** Free log_io memory and destroy it cleanly, without side
- * effects (for use in the atfork handler).
- */
-void
-log_io_atfork(struct log_io **lptr)
-{
-	struct log_io *l = *lptr;
-	if (l) {
-		/*
-		 * Close the file descriptor STDIO buffer does not
-		 * make its way into the respective file in
-		 * fclose().
-		 */
-		close(fileno(l->f));
-		fclose(l->f);
-		free(l);
-		*lptr = NULL;
-	}
-}
-
-static int
-sync_cb(eio_req *req)
-{
-	if (req->result)
-		say_error("%s: fsync failed, errno: %d",
-			  __func__, (int) req->result);
-
-	int fd = (intptr_t) req->data;
-	close(fd);
-	return 0;
-}
-
-int
-log_io_sync(struct log_io *l)
-{
-	if (l->dir->sync_is_async) {
-		int fd = dup(fileno(l->f));
-		if (fd == -1) {
-			say_syserror("%s: dup() failed", __func__);
-			return -1;
-		}
-		eio_fsync(fd, 0, sync_cb, (void *) (intptr_t) fd);
-	} else if (fsync(fileno(l->f)) < 0) {
-		say_syserror("%s: fsync failed", l->filename);
-		return -1;
-	}
-	return 0;
-}
-
-static int
-log_io_write_header(struct log_io *l)
-{
-	int ret = fprintf(l->f, "%s%s\n", l->dir->filetype, v11);
-
-	return ret < 0 ? -1 : 0;
-}
-
-/**
- * Verify that file is of the given format.
- *
- * @param l		log_io object, denoting the file to check.
- * @param[out] errmsg   set if error
- *
- * @return 0 if success, -1 on error.
- */
-static int
-log_io_verify_meta(struct log_io *l, const char **errmsg)
-{
-	char filetype[32], version[32], buf[256];
-	struct log_dir *dir = l->dir;
-	FILE *stream = l->f;
-
-	if (fgets(filetype, sizeof(filetype), stream) == NULL ||
-	    fgets(version, sizeof(version), stream) == NULL) {
-		*errmsg = "failed to read log file header";
-		goto error;
-	}
-	if (strcmp(dir->filetype, filetype) != 0) {
-		*errmsg = "unknown filetype";
-		goto error;
-	}
-
-	if (strcmp(v11, version) != 0) {
-		*errmsg = "unknown version";
-		goto error;
-	}
-	for (;;) {
-		if (fgets(buf, sizeof(buf), stream) == NULL) {
-			*errmsg = "failed to read log file header";
-			goto error;
-		}
-		if (strcmp(buf, "\n") == 0 || strcmp(buf, "\r\n") == 0)
-			break;
-	}
-	return 0;
-error:
-	return -1;
-}
-
-struct log_io *
-log_io_open(struct log_dir *dir, enum log_mode mode,
-	    const char *filename, enum log_suffix suffix, FILE *file)
-{
-	struct log_io *l = NULL;
-	int save_errno;
-	const char *errmsg = NULL;
-	/*
-	 * Check fopen() result the caller first thing, to
-	 * preserve the errno.
-	 */
-	if (file == NULL) {
-		errmsg = strerror(errno);
-		goto error;
-	}
-	l = (struct log_io *) calloc(1, sizeof(*l));
-	if (l == NULL) {
-		errmsg = strerror(errno);
-		goto error;
-	}
-	l->f = file;
-	strncpy(l->filename, filename, PATH_MAX);
-	l->mode = mode;
-	l->dir = dir;
-	l->is_inprogress = suffix == INPROGRESS;
-	if (mode == LOG_READ) {
-		if (log_io_verify_meta(l, &errmsg) != 0) {
-			errmsg = strerror(errno);
-			goto error;
-		}
-	} else { /* LOG_WRITE */
-		setvbuf(l->f, NULL, _IONBF, 0);
-		if (log_io_write_header(l) != 0) {
-			errmsg = strerror(errno);
-			goto error;
-		}
-	}
-	return l;
-error:
-	save_errno = errno;
-	say_error("%s: failed to open %s: %s", __func__, filename, errmsg);
-	if (file)
-		fclose(file);
-	if (l)
-		free(l);
-	errno = save_errno;
-	return NULL;
-}
-
-struct log_io *
-log_io_open_for_read(struct log_dir *dir, int64_t lsn, enum log_suffix suffix)
-{
-	assert(lsn != 0);
-
-	const char *filename = format_filename(dir, lsn, suffix);
-	FILE *f = fopen(filename, "r");
-	return log_io_open(dir, LOG_READ, filename, suffix, f);
-}
-
-/**
- * In case of error, writes a message to the server log
- * and sets errno.
- */
-struct log_io *
-log_io_open_for_write(struct log_dir *dir, int64_t lsn, enum log_suffix suffix)
-{
-	char *filename;
-	FILE *f;
-	assert(lsn != 0);
-
-	if (suffix == INPROGRESS) {
-		/*
-		 * Check whether a file with this name already exists.
-		 * We don't overwrite existing files.
-		 */
-		filename = format_filename(dir, lsn, NONE);
-		if (access(filename, F_OK) == 0) {
-			errno = EEXIST;
-			goto error;
-		}
-	}
-	filename = format_filename(dir, lsn, suffix);
-	/*
-	 * Open the <lsn>.<suffix>.inprogress file. If it exists,
-	 * open will fail.
-	 */
-	f = fiob_open(filename, dir->open_wflags);
-
-	if (!f)
-		goto error;
-	say_info("creating `%s'", filename);
-	return log_io_open(dir, LOG_WRITE, filename, suffix, f);
-error:
-	say_syserror("%s: failed to open `%s'", __func__, filename);
-	return NULL;
-}
-
-/* }}} */
-
diff --git a/src/lua/session.cc b/src/lua/session.cc
deleted file mode 100644
index 8d14d3c0071527b5346d109e1b2bccd9bef5594b..0000000000000000000000000000000000000000
--- a/src/lua/session.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "lua/session.h"
-#include "lua/init.h"
-
-extern "C" {
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-
-#include "fiber.h"
-#include "session.h"
-#include "sio.h"
-
-static const char *sessionlib_name = "box.session";
-extern lua_State *root_L;
-
-/**
- * Return a unique monotonic session
- * identifier. The identifier can be used
- * to check whether or not a session is alive.
- * 0 means there is no session (e.g.
- * a procedure is running in a detached
- * fiber).
- */
-static int
-lbox_session_id(struct lua_State *L)
-{
-	lua_pushnumber(L, fiber_ptr->sid);
-	return 1;
-}
-
-/**
- * Check whether or not a session exists.
- */
-static int
-lbox_session_exists(struct lua_State *L)
-{
-	if (lua_gettop(L) != 1)
-		luaL_error(L, "session.exists(sid): bad arguments");
-
-	uint32_t sid = luaL_checkint(L, -1);
-	lua_pushnumber(L, session_exists(sid));
-	return 1;
-}
-
-/**
- * Pretty print peer name.
- */
-static int
-lbox_session_peer(struct lua_State *L)
-{
-	if (lua_gettop(L) > 1)
-		luaL_error(L, "session.peer(sid): bad arguments");
-
-	uint32_t sid = lua_gettop(L) == 1 ?
-		luaL_checkint(L, -1) : fiber_ptr->sid;
-
-	int fd = session_fd(sid);
-	struct sockaddr_in addr;
-	sio_getpeername(fd, &addr);
-
-	lua_pushstring(L, sio_strfaddr(&addr));
-	return 1;
-}
-
-struct lbox_session_trigger
-{
-	struct session_trigger *trigger;
-	int ref;
-};
-
-static struct lbox_session_trigger on_connect =
-	{ &session_on_connect, LUA_NOREF};
-static struct lbox_session_trigger on_disconnect =
-	{ &session_on_disconnect, LUA_NOREF};
-
-static void
-lbox_session_run_trigger(void *param)
-{
-	struct lbox_session_trigger *trigger =
-			(struct lbox_session_trigger *) param;
-	/* Copy the referenced callable object object stack. */
-	lua_State *L = lua_newthread(tarantool_L);
-	int coro_ref = luaL_ref(tarantool_L, LUA_REGISTRYINDEX);
-	lua_rawgeti(tarantool_L, LUA_REGISTRYINDEX, trigger->ref);
-	/** Move the function to be called to the new coro. */
-	lua_xmove(tarantool_L, L, 1);
-
-	try {
-		lua_call(L, 0, 0);
-		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
-	} catch (const Exception& e) {
-		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
-		throw;
-	} catch (...) {
-		luaL_unref(tarantool_L, LUA_REGISTRYINDEX, coro_ref);
-		tnt_raise(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
-	}
-}
-
-static int
-lbox_session_set_trigger(struct lua_State *L,
-			 struct lbox_session_trigger *trigger)
-{
-	if (lua_gettop(L) != 1 ||
-	    (lua_type(L, -1) != LUA_TFUNCTION &&
-	     lua_type(L, -1) != LUA_TNIL)) {
-		luaL_error(L, "session.on_connect(chunk): bad arguments");
-	}
-
-	/* Pop the old trigger */
-	if (trigger->ref != LUA_NOREF) {
-		lua_rawgeti(L, LUA_REGISTRYINDEX, trigger->ref);
-		luaL_unref(L, LUA_REGISTRYINDEX, trigger->ref);
-	} else {
-		lua_pushnil(L);
-	}
-
-	/*
-	 * Set or clear the trigger. Return the old value of the
-	 * trigger.
-	 */
-	if (lua_type(L, -2) == LUA_TNIL) {
-		trigger->ref = LUA_NOREF;
-		trigger->trigger->trigger = NULL;
-		trigger->trigger->param = NULL;
-	} else {
-		/* Move the trigger to the top of the stack. */
-		lua_insert(L, -2);
-		/* Reference the new trigger. Pops it. */
-		trigger->ref = luaL_ref(L, LUA_REGISTRYINDEX);
-		trigger->trigger->trigger = lbox_session_run_trigger;
-		trigger->trigger->param = trigger;
-	}
-	/* Return the old trigger. */
-	return 1;
-}
-
-static int
-lbox_session_on_connect(struct lua_State *L)
-{
-	return lbox_session_set_trigger(L, &on_connect);
-}
-
-static int
-lbox_session_on_disconnect(struct lua_State *L)
-{
-	return lbox_session_set_trigger(L, &on_disconnect);
-}
-
-void
-session_storage_cleanup(int sid)
-{
-	static int ref = LUA_REFNIL;
-
-	int top = lua_gettop(root_L);
-
-	if (ref == LUA_REFNIL) {
-		lua_getfield(root_L, LUA_GLOBALSINDEX, "box");
-		lua_getfield(root_L, -1, "session");
-		lua_getmetatable(root_L, -1);
-		lua_getfield(root_L, -1, "aggregate_storage");
-		ref = luaL_ref(root_L, LUA_REGISTRYINDEX);
-	}
-	lua_rawgeti(root_L, LUA_REGISTRYINDEX, ref);
-
-	lua_pushnil(root_L);
-	lua_rawseti(root_L, -2, sid);
-	lua_settop(root_L, top);
-}
-
-static const struct luaL_reg sessionlib[] = {
-	{"id", lbox_session_id},
-	{"exists", lbox_session_exists},
-	{"peer", lbox_session_peer},
-	{"on_connect", lbox_session_on_connect},
-	{"on_disconnect", lbox_session_on_disconnect},
-	{NULL, NULL}
-};
-
-void
-tarantool_lua_session_init(struct lua_State *L)
-{
-	luaL_register(L, sessionlib_name, sessionlib);
-	lua_pop(L, 1);
-}
diff --git a/src/memcached-grammar.cc b/src/memcached-grammar.cc
deleted file mode 100644
index 3cf79e01bd414f4e78ae5f77dadb7e555ea1a412..0000000000000000000000000000000000000000
--- a/src/memcached-grammar.cc
+++ /dev/null
@@ -1,3671 +0,0 @@
-
-#line 1 "src/memcached-grammar.rl"
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-
-#line 34 "src/memcached-grammar.cc"
-static const int memcached_start = 1;
-static const int memcached_first_final = 197;
-static const int memcached_error = 0;
-
-static const int memcached_en_main = 1;
-
-
-#line 33 "src/memcached-grammar.rl"
-
-
-static int __attribute__((noinline))
-memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
-{
-	int cs;
-	char *p, *pe;
-	char *fstart;
-	struct tbuf *keys = tbuf_new(fiber_ptr->gc_pool);
-	const char *key;
-	bool append, show_cas;
-	int incr_sign;
-	uint64_t cas, incr;
-	uint32_t flags, exptime, bytes;
-	bool noreply = false;
-	char *data = NULL;
-	bool done = false;
-	uintptr_t flush_delay = 0;
-	size_t keys_count = 0;
-	struct ibuf *in = &iobuf->in;
-	struct obuf *out = &iobuf->out;
-	/* Savepoint for 'noreply' */
-	struct obuf_svp obuf_svp = obuf_create_svp(out);
-
-	p = in->pos;
-	pe = in->end;
-
-	say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p);
-
-	
-#line 73 "src/memcached-grammar.cc"
-	{
-	cs = memcached_start;
-	}
-
-#line 78 "src/memcached-grammar.cc"
-	{
-	if ( p == pe )
-		goto _test_eof;
-	switch ( cs )
-	{
-case 1:
-	switch( (*p) ) {
-		case 65: goto st2;
-		case 67: goto st44;
-		case 68: goto st67;
-		case 70: goto st103;
-		case 71: goto st124;
-		case 73: goto st132;
-		case 80: goto st136;
-		case 81: goto st143;
-		case 82: goto st148;
-		case 83: goto st172;
-		case 97: goto st2;
-		case 99: goto st44;
-		case 100: goto st67;
-		case 102: goto st103;
-		case 103: goto st124;
-		case 105: goto st132;
-		case 112: goto st136;
-		case 113: goto st143;
-		case 114: goto st148;
-		case 115: goto st172;
-	}
-	goto st0;
-st0:
-cs = 0;
-	goto _out;
-st2:
-	if ( ++p == pe )
-		goto _test_eof2;
-case 2:
-	switch( (*p) ) {
-		case 68: goto st3;
-		case 80: goto st22;
-		case 100: goto st3;
-		case 112: goto st22;
-	}
-	goto st0;
-st3:
-	if ( ++p == pe )
-		goto _test_eof3;
-case 3:
-	switch( (*p) ) {
-		case 68: goto st4;
-		case 100: goto st4;
-	}
-	goto st0;
-st4:
-	if ( ++p == pe )
-		goto _test_eof4;
-case 4:
-	if ( (*p) == 32 )
-		goto st5;
-	goto st0;
-st5:
-	if ( ++p == pe )
-		goto _test_eof5;
-case 5:
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st5;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr15;
-tr15:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st6;
-st6:
-	if ( ++p == pe )
-		goto _test_eof6;
-case 6:
-#line 166 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st7;
-	goto st0;
-st7:
-	if ( ++p == pe )
-		goto _test_eof7;
-case 7:
-	if ( (*p) == 32 )
-		goto st7;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr17;
-	goto st0;
-tr17:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st8;
-st8:
-	if ( ++p == pe )
-		goto _test_eof8;
-case 8:
-#line 187 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr18;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st8;
-	goto st0;
-tr18:
-#line 244 "src/memcached-grammar.rl"
-	{flags = memcached_natoq(fstart, p);}
-	goto st9;
-st9:
-	if ( ++p == pe )
-		goto _test_eof9;
-case 9:
-#line 201 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st9;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr21;
-	goto st0;
-tr21:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st10;
-st10:
-	if ( ++p == pe )
-		goto _test_eof10;
-case 10:
-#line 215 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr22;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st10;
-	goto st0;
-tr22:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st11;
-st11:
-	if ( ++p == pe )
-		goto _test_eof11;
-case 11:
-#line 233 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st11;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr25;
-	goto st0;
-tr25:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st12;
-st12:
-	if ( ++p == pe )
-		goto _test_eof12;
-case 12:
-#line 247 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr26;
-		case 13: goto tr27;
-		case 32: goto tr28;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st12;
-	goto st0;
-tr26:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 68 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple != NULL && !memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr30:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 68 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple != NULL && !memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr39:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 68 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple != NULL && !memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr58:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 97 "src/memcached-grammar.rl"
-	{
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL) {
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			} else {
-				field = tuple_field(tuple, 3, &field_len);
-				b = tbuf_new(fiber_ptr->gc_pool);
-				if (append) {
-					tbuf_append(b, field, field_len);
-					tbuf_append(b, data, bytes);
-				} else {
-					tbuf_append(b, data, bytes);
-					tbuf_append(b, field, field_len);
-				}
-
-				bytes += field_len;
-				data = b->data;
-				STORE;
-			}
-		}
-	goto st197;
-tr62:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 97 "src/memcached-grammar.rl"
-	{
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL) {
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			} else {
-				field = tuple_field(tuple, 3, &field_len);
-				b = tbuf_new(fiber_ptr->gc_pool);
-				if (append) {
-					tbuf_append(b, field, field_len);
-					tbuf_append(b, data, bytes);
-				} else {
-					tbuf_append(b, data, bytes);
-					tbuf_append(b, field, field_len);
-				}
-
-				bytes += field_len;
-				data = b->data;
-				STORE;
-			}
-		}
-	goto st197;
-tr71:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 97 "src/memcached-grammar.rl"
-	{
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL) {
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			} else {
-				field = tuple_field(tuple, 3, &field_len);
-				b = tbuf_new(fiber_ptr->gc_pool);
-				if (append) {
-					tbuf_append(b, field, field_len);
-					tbuf_append(b, data, bytes);
-				} else {
-					tbuf_append(b, data, bytes);
-					tbuf_append(b, field, field_len);
-				}
-
-				bytes += field_len;
-				data = b->data;
-				STORE;
-			}
-		}
-	goto st197;
-tr91:
-#line 246 "src/memcached-grammar.rl"
-	{cas = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 86 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			else if (memcached_meta(tuple)->cas != cas)
-				obuf_dup(out, "EXISTS\r\n", 8);
-			else
-				STORE;
-		}
-	goto st197;
-tr95:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 86 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			else if (memcached_meta(tuple)->cas != cas)
-				obuf_dup(out, "EXISTS\r\n", 8);
-			else
-				STORE;
-		}
-	goto st197;
-tr105:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 86 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			else if (memcached_meta(tuple)->cas != cas)
-				obuf_dup(out, "EXISTS\r\n", 8);
-			else
-				STORE;
-		}
-	goto st197;
-tr118:
-#line 247 "src/memcached-grammar.rl"
-	{incr = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 123 "src/memcached-grammar.rl"
-	{
-			struct meta *m;
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-			uint64_t value;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				m = memcached_meta(tuple);
-				field = tuple_field(tuple, 3, &field_len);
-
-				if (memcached_is_numeric(field, field_len)) {
-					value = memcached_natoq(field,
-								field + field_len);
-
-					if (incr_sign > 0) {
-						value += incr;
-					} else {
-						if (incr > value)
-							value = 0;
-						else
-							value -= incr;
-					}
-
-					exptime = m->exptime;
-					flags = m->flags;
-
-					b = tbuf_new(fiber_ptr->gc_pool);
-					tbuf_printf(b, "%" PRIu64, value);
-					data = b->data;
-					bytes = b->size;
-
-					stats.cmd_set++;
-					try {
-						memcached_store(key, exptime, flags, bytes, data);
-						stats.total_items++;
-						obuf_dup(out, b->data, b->size);
-						obuf_dup(out, "\r\n", 2);
-					} catch (const ClientError& e) {
-						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-						obuf_dup(out, "\r\n", 2);
-					}
-				} else {
-					obuf_dup(out, "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 62);
-				}
-			}
-
-		}
-	goto st197;
-tr122:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 123 "src/memcached-grammar.rl"
-	{
-			struct meta *m;
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-			uint64_t value;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				m = memcached_meta(tuple);
-				field = tuple_field(tuple, 3, &field_len);
-
-				if (memcached_is_numeric(field, field_len)) {
-					value = memcached_natoq(field,
-								field + field_len);
-
-					if (incr_sign > 0) {
-						value += incr;
-					} else {
-						if (incr > value)
-							value = 0;
-						else
-							value -= incr;
-					}
-
-					exptime = m->exptime;
-					flags = m->flags;
-
-					b = tbuf_new(fiber_ptr->gc_pool);
-					tbuf_printf(b, "%" PRIu64, value);
-					data = b->data;
-					bytes = b->size;
-
-					stats.cmd_set++;
-					try {
-						memcached_store(key, exptime, flags, bytes, data);
-						stats.total_items++;
-						obuf_dup(out, b->data, b->size);
-						obuf_dup(out, "\r\n", 2);
-					} catch (const ClientError& e) {
-						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-						obuf_dup(out, "\r\n", 2);
-					}
-				} else {
-					obuf_dup(out, "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 62);
-				}
-			}
-
-		}
-	goto st197;
-tr132:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 123 "src/memcached-grammar.rl"
-	{
-			struct meta *m;
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-			uint64_t value;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				m = memcached_meta(tuple);
-				field = tuple_field(tuple, 3, &field_len);
-
-				if (memcached_is_numeric(field, field_len)) {
-					value = memcached_natoq(field,
-								field + field_len);
-
-					if (incr_sign > 0) {
-						value += incr;
-					} else {
-						if (incr > value)
-							value = 0;
-						else
-							value -= incr;
-					}
-
-					exptime = m->exptime;
-					flags = m->flags;
-
-					b = tbuf_new(fiber_ptr->gc_pool);
-					tbuf_printf(b, "%" PRIu64, value);
-					data = b->data;
-					bytes = b->size;
-
-					stats.cmd_set++;
-					try {
-						memcached_store(key, exptime, flags, bytes, data);
-						stats.total_items++;
-						obuf_dup(out, b->data, b->size);
-						obuf_dup(out, "\r\n", 2);
-					} catch (const ClientError& e) {
-						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-						obuf_dup(out, "\r\n", 2);
-					}
-				} else {
-					obuf_dup(out, "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 62);
-				}
-			}
-
-		}
-	goto st197;
-tr141:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 177 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				try {
-					memcached_delete(key);
-					obuf_dup(out, "DELETED\r\n", 9);
-				}
-				catch (const ClientError& e) {
-					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-					obuf_dup(out, "\r\n", 2);
-				}
-			}
-		}
-	goto st197;
-tr146:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 177 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				try {
-					memcached_delete(key);
-					obuf_dup(out, "DELETED\r\n", 9);
-				}
-				catch (const ClientError& e) {
-					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-					obuf_dup(out, "\r\n", 2);
-				}
-			}
-		}
-	goto st197;
-tr157:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 177 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				try {
-					memcached_delete(key);
-					obuf_dup(out, "DELETED\r\n", 9);
-				}
-				catch (const ClientError& e) {
-					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-					obuf_dup(out, "\r\n", 2);
-				}
-			}
-		}
-	goto st197;
-tr169:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 206 "src/memcached-grammar.rl"
-	{
-			struct fiber *f = fiber_new("flush_all",
-						    memcached_flush_all);
-			fiber_call(f, flush_delay);
-			obuf_dup(out, "OK\r\n", 4);
-		}
-	goto st197;
-tr174:
-#line 248 "src/memcached-grammar.rl"
-	{flush_delay = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 206 "src/memcached-grammar.rl"
-	{
-			struct fiber *f = fiber_new("flush_all",
-						    memcached_flush_all);
-			fiber_call(f, flush_delay);
-			obuf_dup(out, "OK\r\n", 4);
-		}
-	goto st197;
-tr185:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 206 "src/memcached-grammar.rl"
-	{
-			struct fiber *f = fiber_new("flush_all",
-						    memcached_flush_all);
-			fiber_call(f, flush_delay);
-			obuf_dup(out, "OK\r\n", 4);
-		}
-	goto st197;
-tr195:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 195 "src/memcached-grammar.rl"
-	{
-			try {
-				memcached_get(out, keys_count, keys, show_cas);
-			} catch (const ClientError& e) {
-				obuf_rollback_to_svp(out, &obuf_svp);
-				obuf_dup(out, "SERVER_ERROR ", 13);
-				obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-				obuf_dup(out, "\r\n", 2);
-			}
-		}
-	goto st197;
-tr213:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 217 "src/memcached-grammar.rl"
-	{
-			return -1;
-		}
-	goto st197;
-tr233:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 77 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr237:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 77 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr246:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 77 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-	goto st197;
-tr263:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 63 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			STORE;
-		}
-	goto st197;
-tr267:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 63 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			STORE;
-		}
-	goto st197;
-tr276:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 250 "src/memcached-grammar.rl"
-	{
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 63 "src/memcached-grammar.rl"
-	{
-			key = tbuf_read_field(keys);
-			STORE;
-		}
-	goto st197;
-tr281:
-#line 279 "src/memcached-grammar.rl"
-	{ p++; }
-#line 273 "src/memcached-grammar.rl"
-	{
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-#line 213 "src/memcached-grammar.rl"
-	{
-			memcached_print_stats(out);
-		}
-	goto st197;
-st197:
-	if ( ++p == pe )
-		goto _test_eof197;
-case 197:
-#line 1347 "src/memcached-grammar.cc"
-	goto st0;
-tr27:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st13;
-tr40:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st13;
-st13:
-	if ( ++p == pe )
-		goto _test_eof13;
-case 13:
-#line 1361 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr30;
-	goto st0;
-tr28:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st14;
-st14:
-	if ( ++p == pe )
-		goto _test_eof14;
-case 14:
-#line 1373 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 32: goto st14;
-		case 78: goto st15;
-		case 110: goto st15;
-	}
-	goto st0;
-st15:
-	if ( ++p == pe )
-		goto _test_eof15;
-case 15:
-	switch( (*p) ) {
-		case 79: goto st16;
-		case 111: goto st16;
-	}
-	goto st0;
-st16:
-	if ( ++p == pe )
-		goto _test_eof16;
-case 16:
-	switch( (*p) ) {
-		case 82: goto st17;
-		case 114: goto st17;
-	}
-	goto st0;
-st17:
-	if ( ++p == pe )
-		goto _test_eof17;
-case 17:
-	switch( (*p) ) {
-		case 69: goto st18;
-		case 101: goto st18;
-	}
-	goto st0;
-st18:
-	if ( ++p == pe )
-		goto _test_eof18;
-case 18:
-	switch( (*p) ) {
-		case 80: goto st19;
-		case 112: goto st19;
-	}
-	goto st0;
-st19:
-	if ( ++p == pe )
-		goto _test_eof19;
-case 19:
-	switch( (*p) ) {
-		case 76: goto st20;
-		case 108: goto st20;
-	}
-	goto st0;
-st20:
-	if ( ++p == pe )
-		goto _test_eof20;
-case 20:
-	switch( (*p) ) {
-		case 89: goto st21;
-		case 121: goto st21;
-	}
-	goto st0;
-st21:
-	if ( ++p == pe )
-		goto _test_eof21;
-case 21:
-	switch( (*p) ) {
-		case 10: goto tr39;
-		case 13: goto tr40;
-	}
-	goto st0;
-st22:
-	if ( ++p == pe )
-		goto _test_eof22;
-case 22:
-	switch( (*p) ) {
-		case 80: goto st23;
-		case 112: goto st23;
-	}
-	goto st0;
-st23:
-	if ( ++p == pe )
-		goto _test_eof23;
-case 23:
-	switch( (*p) ) {
-		case 69: goto st24;
-		case 101: goto st24;
-	}
-	goto st0;
-st24:
-	if ( ++p == pe )
-		goto _test_eof24;
-case 24:
-	switch( (*p) ) {
-		case 78: goto st25;
-		case 110: goto st25;
-	}
-	goto st0;
-st25:
-	if ( ++p == pe )
-		goto _test_eof25;
-case 25:
-	switch( (*p) ) {
-		case 68: goto st26;
-		case 100: goto st26;
-	}
-	goto st0;
-st26:
-	if ( ++p == pe )
-		goto _test_eof26;
-case 26:
-	if ( (*p) == 32 )
-		goto tr45;
-	goto st0;
-tr45:
-#line 287 "src/memcached-grammar.rl"
-	{append = true; }
-	goto st27;
-tr209:
-#line 288 "src/memcached-grammar.rl"
-	{append = false;}
-	goto st27;
-st27:
-	if ( ++p == pe )
-		goto _test_eof27;
-case 27:
-#line 1498 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st27;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr46;
-tr46:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st28;
-st28:
-	if ( ++p == pe )
-		goto _test_eof28;
-case 28:
-#line 1523 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st29;
-	goto st0;
-st29:
-	if ( ++p == pe )
-		goto _test_eof29;
-case 29:
-	if ( (*p) == 32 )
-		goto st29;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr49;
-	goto st0;
-tr49:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st30;
-st30:
-	if ( ++p == pe )
-		goto _test_eof30;
-case 30:
-#line 1544 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr50;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st30;
-	goto st0;
-tr50:
-#line 244 "src/memcached-grammar.rl"
-	{flags = memcached_natoq(fstart, p);}
-	goto st31;
-st31:
-	if ( ++p == pe )
-		goto _test_eof31;
-case 31:
-#line 1558 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st31;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr53;
-	goto st0;
-tr53:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st32;
-st32:
-	if ( ++p == pe )
-		goto _test_eof32;
-case 32:
-#line 1572 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr54;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st32;
-	goto st0;
-tr54:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st33;
-st33:
-	if ( ++p == pe )
-		goto _test_eof33;
-case 33:
-#line 1590 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st33;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr57;
-	goto st0;
-tr57:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st34;
-st34:
-	if ( ++p == pe )
-		goto _test_eof34;
-case 34:
-#line 1604 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr58;
-		case 13: goto tr59;
-		case 32: goto tr60;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st34;
-	goto st0;
-tr59:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st35;
-tr72:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st35;
-st35:
-	if ( ++p == pe )
-		goto _test_eof35;
-case 35:
-#line 1625 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr62;
-	goto st0;
-tr60:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st36;
-st36:
-	if ( ++p == pe )
-		goto _test_eof36;
-case 36:
-#line 1637 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 32: goto st36;
-		case 78: goto st37;
-		case 110: goto st37;
-	}
-	goto st0;
-st37:
-	if ( ++p == pe )
-		goto _test_eof37;
-case 37:
-	switch( (*p) ) {
-		case 79: goto st38;
-		case 111: goto st38;
-	}
-	goto st0;
-st38:
-	if ( ++p == pe )
-		goto _test_eof38;
-case 38:
-	switch( (*p) ) {
-		case 82: goto st39;
-		case 114: goto st39;
-	}
-	goto st0;
-st39:
-	if ( ++p == pe )
-		goto _test_eof39;
-case 39:
-	switch( (*p) ) {
-		case 69: goto st40;
-		case 101: goto st40;
-	}
-	goto st0;
-st40:
-	if ( ++p == pe )
-		goto _test_eof40;
-case 40:
-	switch( (*p) ) {
-		case 80: goto st41;
-		case 112: goto st41;
-	}
-	goto st0;
-st41:
-	if ( ++p == pe )
-		goto _test_eof41;
-case 41:
-	switch( (*p) ) {
-		case 76: goto st42;
-		case 108: goto st42;
-	}
-	goto st0;
-st42:
-	if ( ++p == pe )
-		goto _test_eof42;
-case 42:
-	switch( (*p) ) {
-		case 89: goto st43;
-		case 121: goto st43;
-	}
-	goto st0;
-st43:
-	if ( ++p == pe )
-		goto _test_eof43;
-case 43:
-	switch( (*p) ) {
-		case 10: goto tr71;
-		case 13: goto tr72;
-	}
-	goto st0;
-st44:
-	if ( ++p == pe )
-		goto _test_eof44;
-case 44:
-	switch( (*p) ) {
-		case 65: goto st45;
-		case 97: goto st45;
-	}
-	goto st0;
-st45:
-	if ( ++p == pe )
-		goto _test_eof45;
-case 45:
-	switch( (*p) ) {
-		case 83: goto st46;
-		case 115: goto st46;
-	}
-	goto st0;
-st46:
-	if ( ++p == pe )
-		goto _test_eof46;
-case 46:
-	if ( (*p) == 32 )
-		goto st47;
-	goto st0;
-st47:
-	if ( ++p == pe )
-		goto _test_eof47;
-case 47:
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st47;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr76;
-tr76:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st48;
-st48:
-	if ( ++p == pe )
-		goto _test_eof48;
-case 48:
-#line 1760 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st49;
-	goto st0;
-st49:
-	if ( ++p == pe )
-		goto _test_eof49;
-case 49:
-	if ( (*p) == 32 )
-		goto st49;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr78;
-	goto st0;
-tr78:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st50;
-st50:
-	if ( ++p == pe )
-		goto _test_eof50;
-case 50:
-#line 1781 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr79;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st50;
-	goto st0;
-tr79:
-#line 244 "src/memcached-grammar.rl"
-	{flags = memcached_natoq(fstart, p);}
-	goto st51;
-st51:
-	if ( ++p == pe )
-		goto _test_eof51;
-case 51:
-#line 1795 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st51;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr82;
-	goto st0;
-tr82:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st52;
-st52:
-	if ( ++p == pe )
-		goto _test_eof52;
-case 52:
-#line 1809 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr83;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st52;
-	goto st0;
-tr83:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st53;
-st53:
-	if ( ++p == pe )
-		goto _test_eof53;
-case 53:
-#line 1827 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st53;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr86;
-	goto st0;
-tr86:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st54;
-st54:
-	if ( ++p == pe )
-		goto _test_eof54;
-case 54:
-#line 1841 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr87;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st54;
-	goto st0;
-tr87:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st55;
-st55:
-	if ( ++p == pe )
-		goto _test_eof55;
-case 55:
-#line 1855 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st55;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr90;
-	goto st0;
-tr90:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st56;
-st56:
-	if ( ++p == pe )
-		goto _test_eof56;
-case 56:
-#line 1869 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr91;
-		case 13: goto tr92;
-		case 32: goto tr93;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st56;
-	goto st0;
-tr106:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st57;
-tr92:
-#line 246 "src/memcached-grammar.rl"
-	{cas = memcached_natoq(fstart, p);}
-	goto st57;
-st57:
-	if ( ++p == pe )
-		goto _test_eof57;
-case 57:
-#line 1890 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr95;
-	goto st0;
-tr93:
-#line 246 "src/memcached-grammar.rl"
-	{cas = memcached_natoq(fstart, p);}
-	goto st58;
-st58:
-	if ( ++p == pe )
-		goto _test_eof58;
-case 58:
-#line 1902 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr95;
-		case 13: goto st57;
-		case 32: goto st58;
-		case 78: goto st59;
-		case 110: goto st59;
-	}
-	goto st0;
-st59:
-	if ( ++p == pe )
-		goto _test_eof59;
-case 59:
-	switch( (*p) ) {
-		case 79: goto st60;
-		case 111: goto st60;
-	}
-	goto st0;
-st60:
-	if ( ++p == pe )
-		goto _test_eof60;
-case 60:
-	switch( (*p) ) {
-		case 82: goto st61;
-		case 114: goto st61;
-	}
-	goto st0;
-st61:
-	if ( ++p == pe )
-		goto _test_eof61;
-case 61:
-	switch( (*p) ) {
-		case 69: goto st62;
-		case 101: goto st62;
-	}
-	goto st0;
-st62:
-	if ( ++p == pe )
-		goto _test_eof62;
-case 62:
-	switch( (*p) ) {
-		case 80: goto st63;
-		case 112: goto st63;
-	}
-	goto st0;
-st63:
-	if ( ++p == pe )
-		goto _test_eof63;
-case 63:
-	switch( (*p) ) {
-		case 76: goto st64;
-		case 108: goto st64;
-	}
-	goto st0;
-st64:
-	if ( ++p == pe )
-		goto _test_eof64;
-case 64:
-	switch( (*p) ) {
-		case 89: goto st65;
-		case 121: goto st65;
-	}
-	goto st0;
-st65:
-	if ( ++p == pe )
-		goto _test_eof65;
-case 65:
-	switch( (*p) ) {
-		case 10: goto tr105;
-		case 13: goto tr106;
-		case 32: goto tr107;
-	}
-	goto st0;
-tr107:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st66;
-st66:
-	if ( ++p == pe )
-		goto _test_eof66;
-case 66:
-#line 1983 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr95;
-		case 13: goto st57;
-		case 32: goto st66;
-	}
-	goto st0;
-st67:
-	if ( ++p == pe )
-		goto _test_eof67;
-case 67:
-	switch( (*p) ) {
-		case 69: goto st68;
-		case 101: goto st68;
-	}
-	goto st0;
-st68:
-	if ( ++p == pe )
-		goto _test_eof68;
-case 68:
-	switch( (*p) ) {
-		case 67: goto st69;
-		case 76: goto st85;
-		case 99: goto st69;
-		case 108: goto st85;
-	}
-	goto st0;
-st69:
-	if ( ++p == pe )
-		goto _test_eof69;
-case 69:
-	switch( (*p) ) {
-		case 82: goto st70;
-		case 114: goto st70;
-	}
-	goto st0;
-st70:
-	if ( ++p == pe )
-		goto _test_eof70;
-case 70:
-	if ( (*p) == 32 )
-		goto tr113;
-	goto st0;
-tr113:
-#line 296 "src/memcached-grammar.rl"
-	{incr_sign = -1;}
-	goto st71;
-tr202:
-#line 295 "src/memcached-grammar.rl"
-	{incr_sign = 1; }
-	goto st71;
-st71:
-	if ( ++p == pe )
-		goto _test_eof71;
-case 71:
-#line 2038 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st71;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr114;
-tr114:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st72;
-st72:
-	if ( ++p == pe )
-		goto _test_eof72;
-case 72:
-#line 2063 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st73;
-	goto st0;
-st73:
-	if ( ++p == pe )
-		goto _test_eof73;
-case 73:
-	if ( (*p) == 32 )
-		goto st73;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr117;
-	goto st0;
-tr117:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st74;
-st74:
-	if ( ++p == pe )
-		goto _test_eof74;
-case 74:
-#line 2084 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr118;
-		case 13: goto tr119;
-		case 32: goto tr120;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st74;
-	goto st0;
-tr133:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st75;
-tr119:
-#line 247 "src/memcached-grammar.rl"
-	{incr = memcached_natoq(fstart, p);}
-	goto st75;
-st75:
-	if ( ++p == pe )
-		goto _test_eof75;
-case 75:
-#line 2105 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr122;
-	goto st0;
-tr120:
-#line 247 "src/memcached-grammar.rl"
-	{incr = memcached_natoq(fstart, p);}
-	goto st76;
-st76:
-	if ( ++p == pe )
-		goto _test_eof76;
-case 76:
-#line 2117 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr122;
-		case 13: goto st75;
-		case 32: goto st76;
-		case 78: goto st77;
-		case 110: goto st77;
-	}
-	goto st0;
-st77:
-	if ( ++p == pe )
-		goto _test_eof77;
-case 77:
-	switch( (*p) ) {
-		case 79: goto st78;
-		case 111: goto st78;
-	}
-	goto st0;
-st78:
-	if ( ++p == pe )
-		goto _test_eof78;
-case 78:
-	switch( (*p) ) {
-		case 82: goto st79;
-		case 114: goto st79;
-	}
-	goto st0;
-st79:
-	if ( ++p == pe )
-		goto _test_eof79;
-case 79:
-	switch( (*p) ) {
-		case 69: goto st80;
-		case 101: goto st80;
-	}
-	goto st0;
-st80:
-	if ( ++p == pe )
-		goto _test_eof80;
-case 80:
-	switch( (*p) ) {
-		case 80: goto st81;
-		case 112: goto st81;
-	}
-	goto st0;
-st81:
-	if ( ++p == pe )
-		goto _test_eof81;
-case 81:
-	switch( (*p) ) {
-		case 76: goto st82;
-		case 108: goto st82;
-	}
-	goto st0;
-st82:
-	if ( ++p == pe )
-		goto _test_eof82;
-case 82:
-	switch( (*p) ) {
-		case 89: goto st83;
-		case 121: goto st83;
-	}
-	goto st0;
-st83:
-	if ( ++p == pe )
-		goto _test_eof83;
-case 83:
-	switch( (*p) ) {
-		case 10: goto tr132;
-		case 13: goto tr133;
-		case 32: goto tr134;
-	}
-	goto st0;
-tr134:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st84;
-st84:
-	if ( ++p == pe )
-		goto _test_eof84;
-case 84:
-#line 2198 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr122;
-		case 13: goto st75;
-		case 32: goto st84;
-	}
-	goto st0;
-st85:
-	if ( ++p == pe )
-		goto _test_eof85;
-case 85:
-	switch( (*p) ) {
-		case 69: goto st86;
-		case 101: goto st86;
-	}
-	goto st0;
-st86:
-	if ( ++p == pe )
-		goto _test_eof86;
-case 86:
-	switch( (*p) ) {
-		case 84: goto st87;
-		case 116: goto st87;
-	}
-	goto st0;
-st87:
-	if ( ++p == pe )
-		goto _test_eof87;
-case 87:
-	switch( (*p) ) {
-		case 69: goto st88;
-		case 101: goto st88;
-	}
-	goto st0;
-st88:
-	if ( ++p == pe )
-		goto _test_eof88;
-case 88:
-	if ( (*p) == 32 )
-		goto st89;
-	goto st0;
-st89:
-	if ( ++p == pe )
-		goto _test_eof89;
-case 89:
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st89;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr140;
-tr140:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st90;
-st90:
-	if ( ++p == pe )
-		goto _test_eof90;
-case 90:
-#line 2267 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto st91;
-		case 32: goto st92;
-	}
-	goto st0;
-tr147:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st91;
-tr158:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st91;
-st91:
-	if ( ++p == pe )
-		goto _test_eof91;
-case 91:
-#line 2290 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr141;
-	goto st0;
-st92:
-	if ( ++p == pe )
-		goto _test_eof92;
-case 92:
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto st91;
-		case 32: goto st92;
-		case 78: goto st95;
-		case 110: goto st95;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr144;
-	goto st0;
-tr144:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st93;
-st93:
-	if ( ++p == pe )
-		goto _test_eof93;
-case 93:
-#line 2316 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr146;
-		case 13: goto tr147;
-		case 32: goto tr148;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st93;
-	goto st0;
-tr148:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st94;
-st94:
-	if ( ++p == pe )
-		goto _test_eof94;
-case 94:
-#line 2337 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto st91;
-		case 32: goto st94;
-		case 78: goto st95;
-		case 110: goto st95;
-	}
-	goto st0;
-st95:
-	if ( ++p == pe )
-		goto _test_eof95;
-case 95:
-	switch( (*p) ) {
-		case 79: goto st96;
-		case 111: goto st96;
-	}
-	goto st0;
-st96:
-	if ( ++p == pe )
-		goto _test_eof96;
-case 96:
-	switch( (*p) ) {
-		case 82: goto st97;
-		case 114: goto st97;
-	}
-	goto st0;
-st97:
-	if ( ++p == pe )
-		goto _test_eof97;
-case 97:
-	switch( (*p) ) {
-		case 69: goto st98;
-		case 101: goto st98;
-	}
-	goto st0;
-st98:
-	if ( ++p == pe )
-		goto _test_eof98;
-case 98:
-	switch( (*p) ) {
-		case 80: goto st99;
-		case 112: goto st99;
-	}
-	goto st0;
-st99:
-	if ( ++p == pe )
-		goto _test_eof99;
-case 99:
-	switch( (*p) ) {
-		case 76: goto st100;
-		case 108: goto st100;
-	}
-	goto st0;
-st100:
-	if ( ++p == pe )
-		goto _test_eof100;
-case 100:
-	switch( (*p) ) {
-		case 89: goto st101;
-		case 121: goto st101;
-	}
-	goto st0;
-st101:
-	if ( ++p == pe )
-		goto _test_eof101;
-case 101:
-	switch( (*p) ) {
-		case 10: goto tr157;
-		case 13: goto tr158;
-		case 32: goto tr159;
-	}
-	goto st0;
-tr159:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st102;
-st102:
-	if ( ++p == pe )
-		goto _test_eof102;
-case 102:
-#line 2418 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr141;
-		case 13: goto st91;
-		case 32: goto st102;
-	}
-	goto st0;
-st103:
-	if ( ++p == pe )
-		goto _test_eof103;
-case 103:
-	switch( (*p) ) {
-		case 76: goto st104;
-		case 108: goto st104;
-	}
-	goto st0;
-st104:
-	if ( ++p == pe )
-		goto _test_eof104;
-case 104:
-	switch( (*p) ) {
-		case 85: goto st105;
-		case 117: goto st105;
-	}
-	goto st0;
-st105:
-	if ( ++p == pe )
-		goto _test_eof105;
-case 105:
-	switch( (*p) ) {
-		case 83: goto st106;
-		case 115: goto st106;
-	}
-	goto st0;
-st106:
-	if ( ++p == pe )
-		goto _test_eof106;
-case 106:
-	switch( (*p) ) {
-		case 72: goto st107;
-		case 104: goto st107;
-	}
-	goto st0;
-st107:
-	if ( ++p == pe )
-		goto _test_eof107;
-case 107:
-	if ( (*p) == 95 )
-		goto st108;
-	goto st0;
-st108:
-	if ( ++p == pe )
-		goto _test_eof108;
-case 108:
-	switch( (*p) ) {
-		case 65: goto st109;
-		case 97: goto st109;
-	}
-	goto st0;
-st109:
-	if ( ++p == pe )
-		goto _test_eof109;
-case 109:
-	switch( (*p) ) {
-		case 76: goto st110;
-		case 108: goto st110;
-	}
-	goto st0;
-st110:
-	if ( ++p == pe )
-		goto _test_eof110;
-case 110:
-	switch( (*p) ) {
-		case 76: goto st111;
-		case 108: goto st111;
-	}
-	goto st0;
-st111:
-	if ( ++p == pe )
-		goto _test_eof111;
-case 111:
-	switch( (*p) ) {
-		case 10: goto tr169;
-		case 13: goto st112;
-		case 32: goto st113;
-	}
-	goto st0;
-tr186:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st112;
-tr175:
-#line 248 "src/memcached-grammar.rl"
-	{flush_delay = memcached_natoq(fstart, p);}
-	goto st112;
-st112:
-	if ( ++p == pe )
-		goto _test_eof112;
-case 112:
-#line 2517 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr169;
-	goto st0;
-st113:
-	if ( ++p == pe )
-		goto _test_eof113;
-case 113:
-	switch( (*p) ) {
-		case 10: goto tr169;
-		case 13: goto st112;
-		case 32: goto st113;
-		case 78: goto st116;
-		case 110: goto st116;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr172;
-	goto st0;
-tr172:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st114;
-st114:
-	if ( ++p == pe )
-		goto _test_eof114;
-case 114:
-#line 2543 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr174;
-		case 13: goto tr175;
-		case 32: goto tr176;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st114;
-	goto st0;
-tr176:
-#line 248 "src/memcached-grammar.rl"
-	{flush_delay = memcached_natoq(fstart, p);}
-	goto st115;
-st115:
-	if ( ++p == pe )
-		goto _test_eof115;
-case 115:
-#line 2560 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr169;
-		case 13: goto st112;
-		case 32: goto st115;
-		case 78: goto st116;
-		case 110: goto st116;
-	}
-	goto st0;
-st116:
-	if ( ++p == pe )
-		goto _test_eof116;
-case 116:
-	switch( (*p) ) {
-		case 79: goto st117;
-		case 111: goto st117;
-	}
-	goto st0;
-st117:
-	if ( ++p == pe )
-		goto _test_eof117;
-case 117:
-	switch( (*p) ) {
-		case 82: goto st118;
-		case 114: goto st118;
-	}
-	goto st0;
-st118:
-	if ( ++p == pe )
-		goto _test_eof118;
-case 118:
-	switch( (*p) ) {
-		case 69: goto st119;
-		case 101: goto st119;
-	}
-	goto st0;
-st119:
-	if ( ++p == pe )
-		goto _test_eof119;
-case 119:
-	switch( (*p) ) {
-		case 80: goto st120;
-		case 112: goto st120;
-	}
-	goto st0;
-st120:
-	if ( ++p == pe )
-		goto _test_eof120;
-case 120:
-	switch( (*p) ) {
-		case 76: goto st121;
-		case 108: goto st121;
-	}
-	goto st0;
-st121:
-	if ( ++p == pe )
-		goto _test_eof121;
-case 121:
-	switch( (*p) ) {
-		case 89: goto st122;
-		case 121: goto st122;
-	}
-	goto st0;
-st122:
-	if ( ++p == pe )
-		goto _test_eof122;
-case 122:
-	switch( (*p) ) {
-		case 10: goto tr185;
-		case 13: goto tr186;
-		case 32: goto tr187;
-	}
-	goto st0;
-tr187:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st123;
-st123:
-	if ( ++p == pe )
-		goto _test_eof123;
-case 123:
-#line 2641 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr169;
-		case 13: goto st112;
-		case 32: goto st123;
-	}
-	goto st0;
-st124:
-	if ( ++p == pe )
-		goto _test_eof124;
-case 124:
-	switch( (*p) ) {
-		case 69: goto st125;
-		case 101: goto st125;
-	}
-	goto st0;
-st125:
-	if ( ++p == pe )
-		goto _test_eof125;
-case 125:
-	switch( (*p) ) {
-		case 84: goto st126;
-		case 116: goto st126;
-	}
-	goto st0;
-st126:
-	if ( ++p == pe )
-		goto _test_eof126;
-case 126:
-	switch( (*p) ) {
-		case 32: goto tr191;
-		case 83: goto st131;
-		case 115: goto st131;
-	}
-	goto st0;
-tr191:
-#line 292 "src/memcached-grammar.rl"
-	{show_cas = false;}
-	goto st127;
-tr198:
-#line 293 "src/memcached-grammar.rl"
-	{show_cas = true;}
-	goto st127;
-st127:
-	if ( ++p == pe )
-		goto _test_eof127;
-case 127:
-#line 2688 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st127;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr193;
-tr193:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st128;
-st128:
-	if ( ++p == pe )
-		goto _test_eof128;
-case 128:
-#line 2713 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr195;
-		case 13: goto st129;
-		case 32: goto st130;
-	}
-	goto st0;
-st129:
-	if ( ++p == pe )
-		goto _test_eof129;
-case 129:
-	if ( (*p) == 10 )
-		goto tr195;
-	goto st0;
-st130:
-	if ( ++p == pe )
-		goto _test_eof130;
-case 130:
-	switch( (*p) ) {
-		case 9: goto st0;
-		case 10: goto tr195;
-		case 13: goto st129;
-		case 32: goto st130;
-	}
-	goto tr193;
-st131:
-	if ( ++p == pe )
-		goto _test_eof131;
-case 131:
-	if ( (*p) == 32 )
-		goto tr198;
-	goto st0;
-st132:
-	if ( ++p == pe )
-		goto _test_eof132;
-case 132:
-	switch( (*p) ) {
-		case 78: goto st133;
-		case 110: goto st133;
-	}
-	goto st0;
-st133:
-	if ( ++p == pe )
-		goto _test_eof133;
-case 133:
-	switch( (*p) ) {
-		case 67: goto st134;
-		case 99: goto st134;
-	}
-	goto st0;
-st134:
-	if ( ++p == pe )
-		goto _test_eof134;
-case 134:
-	switch( (*p) ) {
-		case 82: goto st135;
-		case 114: goto st135;
-	}
-	goto st0;
-st135:
-	if ( ++p == pe )
-		goto _test_eof135;
-case 135:
-	if ( (*p) == 32 )
-		goto tr202;
-	goto st0;
-st136:
-	if ( ++p == pe )
-		goto _test_eof136;
-case 136:
-	switch( (*p) ) {
-		case 82: goto st137;
-		case 114: goto st137;
-	}
-	goto st0;
-st137:
-	if ( ++p == pe )
-		goto _test_eof137;
-case 137:
-	switch( (*p) ) {
-		case 69: goto st138;
-		case 101: goto st138;
-	}
-	goto st0;
-st138:
-	if ( ++p == pe )
-		goto _test_eof138;
-case 138:
-	switch( (*p) ) {
-		case 80: goto st139;
-		case 112: goto st139;
-	}
-	goto st0;
-st139:
-	if ( ++p == pe )
-		goto _test_eof139;
-case 139:
-	switch( (*p) ) {
-		case 69: goto st140;
-		case 101: goto st140;
-	}
-	goto st0;
-st140:
-	if ( ++p == pe )
-		goto _test_eof140;
-case 140:
-	switch( (*p) ) {
-		case 78: goto st141;
-		case 110: goto st141;
-	}
-	goto st0;
-st141:
-	if ( ++p == pe )
-		goto _test_eof141;
-case 141:
-	switch( (*p) ) {
-		case 68: goto st142;
-		case 100: goto st142;
-	}
-	goto st0;
-st142:
-	if ( ++p == pe )
-		goto _test_eof142;
-case 142:
-	if ( (*p) == 32 )
-		goto tr209;
-	goto st0;
-st143:
-	if ( ++p == pe )
-		goto _test_eof143;
-case 143:
-	switch( (*p) ) {
-		case 85: goto st144;
-		case 117: goto st144;
-	}
-	goto st0;
-st144:
-	if ( ++p == pe )
-		goto _test_eof144;
-case 144:
-	switch( (*p) ) {
-		case 73: goto st145;
-		case 105: goto st145;
-	}
-	goto st0;
-st145:
-	if ( ++p == pe )
-		goto _test_eof145;
-case 145:
-	switch( (*p) ) {
-		case 84: goto st146;
-		case 116: goto st146;
-	}
-	goto st0;
-st146:
-	if ( ++p == pe )
-		goto _test_eof146;
-case 146:
-	switch( (*p) ) {
-		case 10: goto tr213;
-		case 13: goto st147;
-	}
-	goto st0;
-st147:
-	if ( ++p == pe )
-		goto _test_eof147;
-case 147:
-	if ( (*p) == 10 )
-		goto tr213;
-	goto st0;
-st148:
-	if ( ++p == pe )
-		goto _test_eof148;
-case 148:
-	switch( (*p) ) {
-		case 69: goto st149;
-		case 101: goto st149;
-	}
-	goto st0;
-st149:
-	if ( ++p == pe )
-		goto _test_eof149;
-case 149:
-	switch( (*p) ) {
-		case 80: goto st150;
-		case 112: goto st150;
-	}
-	goto st0;
-st150:
-	if ( ++p == pe )
-		goto _test_eof150;
-case 150:
-	switch( (*p) ) {
-		case 76: goto st151;
-		case 108: goto st151;
-	}
-	goto st0;
-st151:
-	if ( ++p == pe )
-		goto _test_eof151;
-case 151:
-	switch( (*p) ) {
-		case 65: goto st152;
-		case 97: goto st152;
-	}
-	goto st0;
-st152:
-	if ( ++p == pe )
-		goto _test_eof152;
-case 152:
-	switch( (*p) ) {
-		case 67: goto st153;
-		case 99: goto st153;
-	}
-	goto st0;
-st153:
-	if ( ++p == pe )
-		goto _test_eof153;
-case 153:
-	switch( (*p) ) {
-		case 69: goto st154;
-		case 101: goto st154;
-	}
-	goto st0;
-st154:
-	if ( ++p == pe )
-		goto _test_eof154;
-case 154:
-	if ( (*p) == 32 )
-		goto st155;
-	goto st0;
-st155:
-	if ( ++p == pe )
-		goto _test_eof155;
-case 155:
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st155;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr222;
-tr222:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st156;
-st156:
-	if ( ++p == pe )
-		goto _test_eof156;
-case 156:
-#line 2972 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st157;
-	goto st0;
-st157:
-	if ( ++p == pe )
-		goto _test_eof157;
-case 157:
-	if ( (*p) == 32 )
-		goto st157;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr224;
-	goto st0;
-tr224:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st158;
-st158:
-	if ( ++p == pe )
-		goto _test_eof158;
-case 158:
-#line 2993 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr225;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st158;
-	goto st0;
-tr225:
-#line 244 "src/memcached-grammar.rl"
-	{flags = memcached_natoq(fstart, p);}
-	goto st159;
-st159:
-	if ( ++p == pe )
-		goto _test_eof159;
-case 159:
-#line 3007 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st159;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr228;
-	goto st0;
-tr228:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st160;
-st160:
-	if ( ++p == pe )
-		goto _test_eof160;
-case 160:
-#line 3021 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr229;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st160;
-	goto st0;
-tr229:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st161;
-st161:
-	if ( ++p == pe )
-		goto _test_eof161;
-case 161:
-#line 3039 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st161;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr232;
-	goto st0;
-tr232:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st162;
-st162:
-	if ( ++p == pe )
-		goto _test_eof162;
-case 162:
-#line 3053 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr233;
-		case 13: goto tr234;
-		case 32: goto tr235;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st162;
-	goto st0;
-tr234:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st163;
-tr247:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st163;
-st163:
-	if ( ++p == pe )
-		goto _test_eof163;
-case 163:
-#line 3074 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr237;
-	goto st0;
-tr235:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st164;
-st164:
-	if ( ++p == pe )
-		goto _test_eof164;
-case 164:
-#line 3086 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 32: goto st164;
-		case 78: goto st165;
-		case 110: goto st165;
-	}
-	goto st0;
-st165:
-	if ( ++p == pe )
-		goto _test_eof165;
-case 165:
-	switch( (*p) ) {
-		case 79: goto st166;
-		case 111: goto st166;
-	}
-	goto st0;
-st166:
-	if ( ++p == pe )
-		goto _test_eof166;
-case 166:
-	switch( (*p) ) {
-		case 82: goto st167;
-		case 114: goto st167;
-	}
-	goto st0;
-st167:
-	if ( ++p == pe )
-		goto _test_eof167;
-case 167:
-	switch( (*p) ) {
-		case 69: goto st168;
-		case 101: goto st168;
-	}
-	goto st0;
-st168:
-	if ( ++p == pe )
-		goto _test_eof168;
-case 168:
-	switch( (*p) ) {
-		case 80: goto st169;
-		case 112: goto st169;
-	}
-	goto st0;
-st169:
-	if ( ++p == pe )
-		goto _test_eof169;
-case 169:
-	switch( (*p) ) {
-		case 76: goto st170;
-		case 108: goto st170;
-	}
-	goto st0;
-st170:
-	if ( ++p == pe )
-		goto _test_eof170;
-case 170:
-	switch( (*p) ) {
-		case 89: goto st171;
-		case 121: goto st171;
-	}
-	goto st0;
-st171:
-	if ( ++p == pe )
-		goto _test_eof171;
-case 171:
-	switch( (*p) ) {
-		case 10: goto tr246;
-		case 13: goto tr247;
-	}
-	goto st0;
-st172:
-	if ( ++p == pe )
-		goto _test_eof172;
-case 172:
-	switch( (*p) ) {
-		case 69: goto st173;
-		case 84: goto st192;
-		case 101: goto st173;
-		case 116: goto st192;
-	}
-	goto st0;
-st173:
-	if ( ++p == pe )
-		goto _test_eof173;
-case 173:
-	switch( (*p) ) {
-		case 84: goto st174;
-		case 116: goto st174;
-	}
-	goto st0;
-st174:
-	if ( ++p == pe )
-		goto _test_eof174;
-case 174:
-	if ( (*p) == 32 )
-		goto st175;
-	goto st0;
-st175:
-	if ( ++p == pe )
-		goto _test_eof175;
-case 175:
-	switch( (*p) ) {
-		case 13: goto st0;
-		case 32: goto st175;
-	}
-	if ( 9 <= (*p) && (*p) <= 10 )
-		goto st0;
-	goto tr252;
-tr252:
-#line 222 "src/memcached-grammar.rl"
-	{
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-	goto st176;
-st176:
-	if ( ++p == pe )
-		goto _test_eof176;
-case 176:
-#line 3211 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st177;
-	goto st0;
-st177:
-	if ( ++p == pe )
-		goto _test_eof177;
-case 177:
-	if ( (*p) == 32 )
-		goto st177;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr254;
-	goto st0;
-tr254:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st178;
-st178:
-	if ( ++p == pe )
-		goto _test_eof178;
-case 178:
-#line 3232 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr255;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st178;
-	goto st0;
-tr255:
-#line 244 "src/memcached-grammar.rl"
-	{flags = memcached_natoq(fstart, p);}
-	goto st179;
-st179:
-	if ( ++p == pe )
-		goto _test_eof179;
-case 179:
-#line 3246 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st179;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr258;
-	goto st0;
-tr258:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st180;
-st180:
-	if ( ++p == pe )
-		goto _test_eof180;
-case 180:
-#line 3260 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto tr259;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st180;
-	goto st0;
-tr259:
-#line 237 "src/memcached-grammar.rl"
-	{
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-	goto st181;
-st181:
-	if ( ++p == pe )
-		goto _test_eof181;
-case 181:
-#line 3278 "src/memcached-grammar.cc"
-	if ( (*p) == 32 )
-		goto st181;
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto tr262;
-	goto st0;
-tr262:
-#line 221 "src/memcached-grammar.rl"
-	{ fstart = p; }
-	goto st182;
-st182:
-	if ( ++p == pe )
-		goto _test_eof182;
-case 182:
-#line 3292 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 10: goto tr263;
-		case 13: goto tr264;
-		case 32: goto tr265;
-	}
-	if ( 48 <= (*p) && (*p) <= 57 )
-		goto st182;
-	goto st0;
-tr264:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st183;
-tr277:
-#line 281 "src/memcached-grammar.rl"
-	{ noreply = true; }
-	goto st183;
-st183:
-	if ( ++p == pe )
-		goto _test_eof183;
-case 183:
-#line 3313 "src/memcached-grammar.cc"
-	if ( (*p) == 10 )
-		goto tr267;
-	goto st0;
-tr265:
-#line 245 "src/memcached-grammar.rl"
-	{bytes = memcached_natoq(fstart, p);}
-	goto st184;
-st184:
-	if ( ++p == pe )
-		goto _test_eof184;
-case 184:
-#line 3325 "src/memcached-grammar.cc"
-	switch( (*p) ) {
-		case 32: goto st184;
-		case 78: goto st185;
-		case 110: goto st185;
-	}
-	goto st0;
-st185:
-	if ( ++p == pe )
-		goto _test_eof185;
-case 185:
-	switch( (*p) ) {
-		case 79: goto st186;
-		case 111: goto st186;
-	}
-	goto st0;
-st186:
-	if ( ++p == pe )
-		goto _test_eof186;
-case 186:
-	switch( (*p) ) {
-		case 82: goto st187;
-		case 114: goto st187;
-	}
-	goto st0;
-st187:
-	if ( ++p == pe )
-		goto _test_eof187;
-case 187:
-	switch( (*p) ) {
-		case 69: goto st188;
-		case 101: goto st188;
-	}
-	goto st0;
-st188:
-	if ( ++p == pe )
-		goto _test_eof188;
-case 188:
-	switch( (*p) ) {
-		case 80: goto st189;
-		case 112: goto st189;
-	}
-	goto st0;
-st189:
-	if ( ++p == pe )
-		goto _test_eof189;
-case 189:
-	switch( (*p) ) {
-		case 76: goto st190;
-		case 108: goto st190;
-	}
-	goto st0;
-st190:
-	if ( ++p == pe )
-		goto _test_eof190;
-case 190:
-	switch( (*p) ) {
-		case 89: goto st191;
-		case 121: goto st191;
-	}
-	goto st0;
-st191:
-	if ( ++p == pe )
-		goto _test_eof191;
-case 191:
-	switch( (*p) ) {
-		case 10: goto tr276;
-		case 13: goto tr277;
-	}
-	goto st0;
-st192:
-	if ( ++p == pe )
-		goto _test_eof192;
-case 192:
-	switch( (*p) ) {
-		case 65: goto st193;
-		case 97: goto st193;
-	}
-	goto st0;
-st193:
-	if ( ++p == pe )
-		goto _test_eof193;
-case 193:
-	switch( (*p) ) {
-		case 84: goto st194;
-		case 116: goto st194;
-	}
-	goto st0;
-st194:
-	if ( ++p == pe )
-		goto _test_eof194;
-case 194:
-	switch( (*p) ) {
-		case 83: goto st195;
-		case 115: goto st195;
-	}
-	goto st0;
-st195:
-	if ( ++p == pe )
-		goto _test_eof195;
-case 195:
-	switch( (*p) ) {
-		case 10: goto tr281;
-		case 13: goto st196;
-	}
-	goto st0;
-st196:
-	if ( ++p == pe )
-		goto _test_eof196;
-case 196:
-	if ( (*p) == 10 )
-		goto tr281;
-	goto st0;
-	}
-	_test_eof2: cs = 2; goto _test_eof; 
-	_test_eof3: cs = 3; goto _test_eof; 
-	_test_eof4: cs = 4; goto _test_eof; 
-	_test_eof5: cs = 5; goto _test_eof; 
-	_test_eof6: cs = 6; goto _test_eof; 
-	_test_eof7: cs = 7; goto _test_eof; 
-	_test_eof8: cs = 8; goto _test_eof; 
-	_test_eof9: cs = 9; goto _test_eof; 
-	_test_eof10: cs = 10; goto _test_eof; 
-	_test_eof11: cs = 11; goto _test_eof; 
-	_test_eof12: cs = 12; goto _test_eof; 
-	_test_eof197: cs = 197; goto _test_eof; 
-	_test_eof13: cs = 13; goto _test_eof; 
-	_test_eof14: cs = 14; goto _test_eof; 
-	_test_eof15: cs = 15; goto _test_eof; 
-	_test_eof16: cs = 16; goto _test_eof; 
-	_test_eof17: cs = 17; goto _test_eof; 
-	_test_eof18: cs = 18; goto _test_eof; 
-	_test_eof19: cs = 19; goto _test_eof; 
-	_test_eof20: cs = 20; goto _test_eof; 
-	_test_eof21: cs = 21; goto _test_eof; 
-	_test_eof22: cs = 22; goto _test_eof; 
-	_test_eof23: cs = 23; goto _test_eof; 
-	_test_eof24: cs = 24; goto _test_eof; 
-	_test_eof25: cs = 25; goto _test_eof; 
-	_test_eof26: cs = 26; goto _test_eof; 
-	_test_eof27: cs = 27; goto _test_eof; 
-	_test_eof28: cs = 28; goto _test_eof; 
-	_test_eof29: cs = 29; goto _test_eof; 
-	_test_eof30: cs = 30; goto _test_eof; 
-	_test_eof31: cs = 31; goto _test_eof; 
-	_test_eof32: cs = 32; goto _test_eof; 
-	_test_eof33: cs = 33; goto _test_eof; 
-	_test_eof34: cs = 34; goto _test_eof; 
-	_test_eof35: cs = 35; goto _test_eof; 
-	_test_eof36: cs = 36; goto _test_eof; 
-	_test_eof37: cs = 37; goto _test_eof; 
-	_test_eof38: cs = 38; goto _test_eof; 
-	_test_eof39: cs = 39; goto _test_eof; 
-	_test_eof40: cs = 40; goto _test_eof; 
-	_test_eof41: cs = 41; goto _test_eof; 
-	_test_eof42: cs = 42; goto _test_eof; 
-	_test_eof43: cs = 43; goto _test_eof; 
-	_test_eof44: cs = 44; goto _test_eof; 
-	_test_eof45: cs = 45; goto _test_eof; 
-	_test_eof46: cs = 46; goto _test_eof; 
-	_test_eof47: cs = 47; goto _test_eof; 
-	_test_eof48: cs = 48; goto _test_eof; 
-	_test_eof49: cs = 49; goto _test_eof; 
-	_test_eof50: cs = 50; goto _test_eof; 
-	_test_eof51: cs = 51; goto _test_eof; 
-	_test_eof52: cs = 52; goto _test_eof; 
-	_test_eof53: cs = 53; goto _test_eof; 
-	_test_eof54: cs = 54; goto _test_eof; 
-	_test_eof55: cs = 55; goto _test_eof; 
-	_test_eof56: cs = 56; goto _test_eof; 
-	_test_eof57: cs = 57; goto _test_eof; 
-	_test_eof58: cs = 58; goto _test_eof; 
-	_test_eof59: cs = 59; goto _test_eof; 
-	_test_eof60: cs = 60; goto _test_eof; 
-	_test_eof61: cs = 61; goto _test_eof; 
-	_test_eof62: cs = 62; goto _test_eof; 
-	_test_eof63: cs = 63; goto _test_eof; 
-	_test_eof64: cs = 64; goto _test_eof; 
-	_test_eof65: cs = 65; goto _test_eof; 
-	_test_eof66: cs = 66; goto _test_eof; 
-	_test_eof67: cs = 67; goto _test_eof; 
-	_test_eof68: cs = 68; goto _test_eof; 
-	_test_eof69: cs = 69; goto _test_eof; 
-	_test_eof70: cs = 70; goto _test_eof; 
-	_test_eof71: cs = 71; goto _test_eof; 
-	_test_eof72: cs = 72; goto _test_eof; 
-	_test_eof73: cs = 73; goto _test_eof; 
-	_test_eof74: cs = 74; goto _test_eof; 
-	_test_eof75: cs = 75; goto _test_eof; 
-	_test_eof76: cs = 76; goto _test_eof; 
-	_test_eof77: cs = 77; goto _test_eof; 
-	_test_eof78: cs = 78; goto _test_eof; 
-	_test_eof79: cs = 79; goto _test_eof; 
-	_test_eof80: cs = 80; goto _test_eof; 
-	_test_eof81: cs = 81; goto _test_eof; 
-	_test_eof82: cs = 82; goto _test_eof; 
-	_test_eof83: cs = 83; goto _test_eof; 
-	_test_eof84: cs = 84; goto _test_eof; 
-	_test_eof85: cs = 85; goto _test_eof; 
-	_test_eof86: cs = 86; goto _test_eof; 
-	_test_eof87: cs = 87; goto _test_eof; 
-	_test_eof88: cs = 88; goto _test_eof; 
-	_test_eof89: cs = 89; goto _test_eof; 
-	_test_eof90: cs = 90; goto _test_eof; 
-	_test_eof91: cs = 91; goto _test_eof; 
-	_test_eof92: cs = 92; goto _test_eof; 
-	_test_eof93: cs = 93; goto _test_eof; 
-	_test_eof94: cs = 94; goto _test_eof; 
-	_test_eof95: cs = 95; goto _test_eof; 
-	_test_eof96: cs = 96; goto _test_eof; 
-	_test_eof97: cs = 97; goto _test_eof; 
-	_test_eof98: cs = 98; goto _test_eof; 
-	_test_eof99: cs = 99; goto _test_eof; 
-	_test_eof100: cs = 100; goto _test_eof; 
-	_test_eof101: cs = 101; goto _test_eof; 
-	_test_eof102: cs = 102; goto _test_eof; 
-	_test_eof103: cs = 103; goto _test_eof; 
-	_test_eof104: cs = 104; goto _test_eof; 
-	_test_eof105: cs = 105; goto _test_eof; 
-	_test_eof106: cs = 106; goto _test_eof; 
-	_test_eof107: cs = 107; goto _test_eof; 
-	_test_eof108: cs = 108; goto _test_eof; 
-	_test_eof109: cs = 109; goto _test_eof; 
-	_test_eof110: cs = 110; goto _test_eof; 
-	_test_eof111: cs = 111; goto _test_eof; 
-	_test_eof112: cs = 112; goto _test_eof; 
-	_test_eof113: cs = 113; goto _test_eof; 
-	_test_eof114: cs = 114; goto _test_eof; 
-	_test_eof115: cs = 115; goto _test_eof; 
-	_test_eof116: cs = 116; goto _test_eof; 
-	_test_eof117: cs = 117; goto _test_eof; 
-	_test_eof118: cs = 118; goto _test_eof; 
-	_test_eof119: cs = 119; goto _test_eof; 
-	_test_eof120: cs = 120; goto _test_eof; 
-	_test_eof121: cs = 121; goto _test_eof; 
-	_test_eof122: cs = 122; goto _test_eof; 
-	_test_eof123: cs = 123; goto _test_eof; 
-	_test_eof124: cs = 124; goto _test_eof; 
-	_test_eof125: cs = 125; goto _test_eof; 
-	_test_eof126: cs = 126; goto _test_eof; 
-	_test_eof127: cs = 127; goto _test_eof; 
-	_test_eof128: cs = 128; goto _test_eof; 
-	_test_eof129: cs = 129; goto _test_eof; 
-	_test_eof130: cs = 130; goto _test_eof; 
-	_test_eof131: cs = 131; goto _test_eof; 
-	_test_eof132: cs = 132; goto _test_eof; 
-	_test_eof133: cs = 133; goto _test_eof; 
-	_test_eof134: cs = 134; goto _test_eof; 
-	_test_eof135: cs = 135; goto _test_eof; 
-	_test_eof136: cs = 136; goto _test_eof; 
-	_test_eof137: cs = 137; goto _test_eof; 
-	_test_eof138: cs = 138; goto _test_eof; 
-	_test_eof139: cs = 139; goto _test_eof; 
-	_test_eof140: cs = 140; goto _test_eof; 
-	_test_eof141: cs = 141; goto _test_eof; 
-	_test_eof142: cs = 142; goto _test_eof; 
-	_test_eof143: cs = 143; goto _test_eof; 
-	_test_eof144: cs = 144; goto _test_eof; 
-	_test_eof145: cs = 145; goto _test_eof; 
-	_test_eof146: cs = 146; goto _test_eof; 
-	_test_eof147: cs = 147; goto _test_eof; 
-	_test_eof148: cs = 148; goto _test_eof; 
-	_test_eof149: cs = 149; goto _test_eof; 
-	_test_eof150: cs = 150; goto _test_eof; 
-	_test_eof151: cs = 151; goto _test_eof; 
-	_test_eof152: cs = 152; goto _test_eof; 
-	_test_eof153: cs = 153; goto _test_eof; 
-	_test_eof154: cs = 154; goto _test_eof; 
-	_test_eof155: cs = 155; goto _test_eof; 
-	_test_eof156: cs = 156; goto _test_eof; 
-	_test_eof157: cs = 157; goto _test_eof; 
-	_test_eof158: cs = 158; goto _test_eof; 
-	_test_eof159: cs = 159; goto _test_eof; 
-	_test_eof160: cs = 160; goto _test_eof; 
-	_test_eof161: cs = 161; goto _test_eof; 
-	_test_eof162: cs = 162; goto _test_eof; 
-	_test_eof163: cs = 163; goto _test_eof; 
-	_test_eof164: cs = 164; goto _test_eof; 
-	_test_eof165: cs = 165; goto _test_eof; 
-	_test_eof166: cs = 166; goto _test_eof; 
-	_test_eof167: cs = 167; goto _test_eof; 
-	_test_eof168: cs = 168; goto _test_eof; 
-	_test_eof169: cs = 169; goto _test_eof; 
-	_test_eof170: cs = 170; goto _test_eof; 
-	_test_eof171: cs = 171; goto _test_eof; 
-	_test_eof172: cs = 172; goto _test_eof; 
-	_test_eof173: cs = 173; goto _test_eof; 
-	_test_eof174: cs = 174; goto _test_eof; 
-	_test_eof175: cs = 175; goto _test_eof; 
-	_test_eof176: cs = 176; goto _test_eof; 
-	_test_eof177: cs = 177; goto _test_eof; 
-	_test_eof178: cs = 178; goto _test_eof; 
-	_test_eof179: cs = 179; goto _test_eof; 
-	_test_eof180: cs = 180; goto _test_eof; 
-	_test_eof181: cs = 181; goto _test_eof; 
-	_test_eof182: cs = 182; goto _test_eof; 
-	_test_eof183: cs = 183; goto _test_eof; 
-	_test_eof184: cs = 184; goto _test_eof; 
-	_test_eof185: cs = 185; goto _test_eof; 
-	_test_eof186: cs = 186; goto _test_eof; 
-	_test_eof187: cs = 187; goto _test_eof; 
-	_test_eof188: cs = 188; goto _test_eof; 
-	_test_eof189: cs = 189; goto _test_eof; 
-	_test_eof190: cs = 190; goto _test_eof; 
-	_test_eof191: cs = 191; goto _test_eof; 
-	_test_eof192: cs = 192; goto _test_eof; 
-	_test_eof193: cs = 193; goto _test_eof; 
-	_test_eof194: cs = 194; goto _test_eof; 
-	_test_eof195: cs = 195; goto _test_eof; 
-	_test_eof196: cs = 196; goto _test_eof; 
-
-	_test_eof: {}
-	_out: {}
-	}
-
-#line 306 "src/memcached-grammar.rl"
-
-
-	if (!done) {
-		say_debug("parse failed after: `%.*s'", (int)(pe - p), p);
-		if (pe - p > (1 << 20)) {
-		exit:
-			say_warn("memcached proto error");
-			obuf_dup(out, "ERROR\r\n", 7);
-			stats.bytes_written += 7;
-			return -1;
-		}
-		char *r;
-		if ((r = (char *) memmem(p, pe - p, "\r\n", 2)) != NULL) {
-			in->pos = r + 2;
-			obuf_dup(out, "CLIENT_ERROR bad command line format\r\n", 38);
-			return 1;
-		}
-		return 0;
-	}
-
-	if (noreply) {
-		obuf_rollback_to_svp(out, &obuf_svp);
-	}
-	return 1;
-}
-
-/*
- * Local Variables:
- * mode: c
- * End:
- * vim: syntax=objc
- */
diff --git a/src/memcached-grammar.rl b/src/memcached-grammar.rl
deleted file mode 100644
index 8b3a00ab5d9175a84a43a6f55771dbaf66040fbe..0000000000000000000000000000000000000000
--- a/src/memcached-grammar.rl
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-%%{
-	machine memcached;
-	write data;
-}%%
-
-static int __attribute__((noinline))
-memcached_dispatch(struct ev_io *coio, struct iobuf *iobuf)
-{
-	int cs;
-	char *p, *pe;
-	char *fstart;
-	struct tbuf *keys = tbuf_new(fiber_ptr->gc_pool);
-	const char *key;
-	bool append, show_cas;
-	int incr_sign;
-	uint64_t cas, incr;
-	uint32_t flags, exptime, bytes;
-	bool noreply = false;
-	char *data = NULL;
-	bool done = false;
-	uintptr_t flush_delay = 0;
-	size_t keys_count = 0;
-	struct ibuf *in = &iobuf->in;
-	struct obuf *out = &iobuf->out;
-	/* Savepoint for 'noreply' */
-	struct obuf_svp obuf_svp = obuf_create_svp(out);
-
-	p = in->pos;
-	pe = in->end;
-
-	say_debug("memcached_dispatch '%.*s'", MIN((int)(pe - p), 40) , p);
-
-	%%{
-		action set {
-			key = tbuf_read_field(keys);
-			STORE;
-		}
-
-		action add {
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple != NULL && !memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-
-		action replace {
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			else
-				STORE;
-		}
-
-		action cas {
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple))
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			else if (memcached_meta(tuple)->cas != cas)
-				obuf_dup(out, "EXISTS\r\n", 8);
-			else
-				STORE;
-		}
-
-		action append_prepend {
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL) {
-				obuf_dup(out, "NOT_STORED\r\n", 12);
-			} else {
-				field = tuple_field(tuple, 3, &field_len);
-				b = tbuf_new(fiber_ptr->gc_pool);
-				if (append) {
-					tbuf_append(b, field, field_len);
-					tbuf_append(b, data, bytes);
-				} else {
-					tbuf_append(b, data, bytes);
-					tbuf_append(b, field, field_len);
-				}
-
-				bytes += field_len;
-				data = b->data;
-				STORE;
-			}
-		}
-
-		action incr_decr {
-			struct meta *m;
-			struct tbuf *b;
-			const char *field;
-			uint32_t field_len;
-			uint64_t value;
-
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				m = memcached_meta(tuple);
-				field = tuple_field(tuple, 3, &field_len);
-
-				if (memcached_is_numeric(field, field_len)) {
-					value = memcached_natoq(field,
-								field + field_len);
-
-					if (incr_sign > 0) {
-						value += incr;
-					} else {
-						if (incr > value)
-							value = 0;
-						else
-							value -= incr;
-					}
-
-					exptime = m->exptime;
-					flags = m->flags;
-
-					b = tbuf_new(fiber_ptr->gc_pool);
-					tbuf_printf(b, "%" PRIu64, value);
-					data = b->data;
-					bytes = b->size;
-
-					stats.cmd_set++;
-					try {
-						memcached_store(key, exptime, flags, bytes, data);
-						stats.total_items++;
-						obuf_dup(out, b->data, b->size);
-						obuf_dup(out, "\r\n", 2);
-					} catch (const ClientError& e) {
-						obuf_dup(out, "SERVER_ERROR ", 13);
-						obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-						obuf_dup(out, "\r\n", 2);
-					}
-				} else {
-					obuf_dup(out, "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 62);
-				}
-			}
-
-		}
-
-		action delete {
-			key = tbuf_read_field(keys);
-			struct tuple *tuple = memcached_find(key);
-			if (tuple == NULL || memcached_is_expired(tuple)) {
-				obuf_dup(out, "NOT_FOUND\r\n", 11);
-			} else {
-				try {
-					memcached_delete(key);
-					obuf_dup(out, "DELETED\r\n", 9);
-				}
-				catch (const ClientError& e) {
-					obuf_dup(out, "SERVER_ERROR ", 13);
-					obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-					obuf_dup(out, "\r\n", 2);
-				}
-			}
-		}
-
-		action get {
-			try {
-				memcached_get(out, keys_count, keys, show_cas);
-			} catch (const ClientError& e) {
-				obuf_rollback_to_svp(out, &obuf_svp);
-				obuf_dup(out, "SERVER_ERROR ", 13);
-				obuf_dup(out, e.errmsg(), strlen(e.errmsg()));
-				obuf_dup(out, "\r\n", 2);
-			}
-		}
-
-		action flush_all {
-			struct fiber *f = fiber_new("flush_all",
-						    memcached_flush_all);
-			fiber_call(f, flush_delay);
-			obuf_dup(out, "OK\r\n", 4);
-		}
-
-		action stats {
-			memcached_print_stats(out);
-		}
-
-		action quit {
-			return -1;
-		}
-
-		action fstart { fstart = p; }
-		action key_start {
-			fstart = p;
-			for (; p < pe && *p != ' ' && *p != '\r' && *p != '\n'; p++);
-			if ( *p == ' ' || *p == '\r' || *p == '\n') {
-				tbuf_store_field(keys, fstart, p - fstart);
-				keys_count++;
-				p--;
-			} else
-				p = fstart;
-		}
-
-
-		printable = [^ \t\r\n];
-		key = printable >key_start ;
-
-		action exptime {
-			exptime = memcached_natoq(fstart, p);
-			if (exptime > 0 && exptime <= 60*60*24*30)
-				exptime = exptime + ev_now();
-		}
-		exptime = digit+ >fstart %exptime;
-
-		flags = digit+ >fstart %{flags = memcached_natoq(fstart, p);};
-		bytes = digit+ >fstart %{bytes = memcached_natoq(fstart, p);};
-		cas_value = digit+ >fstart %{cas = memcached_natoq(fstart, p);};
-		incr_value = digit+ >fstart %{incr = memcached_natoq(fstart, p);};
-		flush_delay = digit+ >fstart %{flush_delay = memcached_natoq(fstart, p);};
-
-		action read_data {
-			size_t parsed = p - in->pos;
-			while (ibuf_size(in) - parsed < bytes + 2) {
-				size_t to_read = bytes + 2 - (pe - p);
-				if (coio_bread(coio, in, to_read) < to_read)
-					return -1; /* premature EOF */
-			}
-			/*
-			 * Buffered read may have reallocated the
-			 * buffer.
-			 */
-			p = in->pos + parsed;
-			pe = in->end;
-
-			data = p;
-
-			if (strncmp((char *)(p + bytes), "\r\n", 2) == 0) {
-				p += bytes + 2;
-			} else {
-				goto exit;
-			}
-		}
-
-		action done {
-			done = true;
-			stats.bytes_read += p - in->pos;
-			in->pos = p;
-		}
-
-		eol = ("\r\n" | "\n") @{ p++; };
-		spc = " "+;
-		noreply = (spc "noreply"i %{ noreply = true; })?;
-		store_command_body = spc key spc flags spc exptime spc bytes noreply eol;
-
-		set = ("set"i store_command_body) @read_data @done @set;
-		add = ("add"i store_command_body) @read_data @done @add;
-		replace = ("replace"i store_command_body) @read_data @done @replace;
-		append  = ("append"i  %{append = true; } store_command_body) @read_data @done @append_prepend;
-		prepend = ("prepend"i %{append = false;} store_command_body) @read_data @done @append_prepend;
-		cas = ("cas"i spc key spc flags spc exptime spc bytes spc cas_value noreply spc?) eol @read_data @done @cas;
-
-
-		get = "get"i %{show_cas = false;} spc key (spc key)* spc? eol @done @get;
-		gets = "gets"i %{show_cas = true;} spc key (spc key)* spc? eol @done @get;
-		delete = "delete"i spc key (spc exptime)? noreply spc? eol @done @delete;
-		incr = "incr"i %{incr_sign = 1; } spc key spc incr_value noreply spc? eol @done @incr_decr;
-		decr = "decr"i %{incr_sign = -1;} spc key spc incr_value noreply spc? eol @done @incr_decr;
-
-		stats = "stats"i eol @done @stats;
-		flush_all = "flush_all"i (spc flush_delay)? noreply spc? eol @done @flush_all;
-		quit = "quit"i eol @done @quit;
-
-	        main := set | cas | add | replace | append | prepend | get | gets | delete | incr | decr | stats | flush_all | quit;
-	        #main := set;
-		write init;
-		write exec;
-	}%%
-
-	if (!done) {
-		say_debug("parse failed after: `%.*s'", (int)(pe - p), p);
-		if (pe - p > (1 << 20)) {
-		exit:
-			say_warn("memcached proto error");
-			obuf_dup(out, "ERROR\r\n", 7);
-			stats.bytes_written += 7;
-			return -1;
-		}
-		char *r;
-		if ((r = (char *) memmem(p, pe - p, "\r\n", 2)) != NULL) {
-			in->pos = r + 2;
-			obuf_dup(out, "CLIENT_ERROR bad command line format\r\n", 38);
-			return 1;
-		}
-		return 0;
-	}
-
-	if (noreply) {
-		obuf_rollback_to_svp(out, &obuf_svp);
-	}
-	return 1;
-}
-
-/*
- * Local Variables:
- * mode: c
- * End:
- * vim: syntax=objc
- */
diff --git a/src/memcached.cc b/src/memcached.cc
deleted file mode 100644
index f137009b03e96baba8f45e7ef14f80d1c66aac5b..0000000000000000000000000000000000000000
--- a/src/memcached.cc
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "memcached.h"
-#include "tarantool.h"
-
-#include <limits.h>
-
-#include "box/box.h"
-#include "box/request.h"
-#include "box/space.h"
-#include "box/port.h"
-#include "box/tuple.h"
-#include "fiber.h"
-extern "C" {
-#include <cfg/warning.h>
-#include <cfg/tarantool_box_cfg.h>
-} /* extern "C" */
-#include "say.h"
-#include "stat.h"
-#include "salloc.h"
-#include "pickle.h"
-#include "coio_buf.h"
-#include "scoped_guard.h"
-
-#define STAT(_)					\
-        _(MEMC_GET, 1)				\
-        _(MEMC_GET_MISS, 2)			\
-	_(MEMC_GET_HIT, 3)			\
-	_(MEMC_EXPIRED_KEYS, 4)
-
-ENUM(memcached_stat, STAT);
-STRS(memcached_stat, STAT);
-
-static int stat_base;
-static struct fiber *memcached_expire = NULL;
-
-static Index *memcached_index;
-static struct iterator *memcached_it;
-
-/* memcached tuple format:
-   <key, meta, data> */
-
-struct meta {
-	uint32_t exptime;
-	uint32_t flags;
-	uint64_t cas;
-} __packed__;
-
-static uint64_t
-memcached_natoq(const char *start, const char *end)
-{
-	uint64_t num = 0;
-	while (start < end) {
-		uint8_t code = *start++;
-		num = num * 10 + (code - '0');
-	}
-	return num;
-}
-
-void
-tbuf_append_field(struct tbuf *b, const char *f)
-{
-	const char *begin = f;
-	uint32_t size = load_varint32(&f);
-	tbuf_append(b, begin, f - begin + size);
-}
-
-void
-tbuf_store_field(struct tbuf *b, const char *field, uint32_t len)
-{
-	char buf[sizeof(uint32_t)+1];
-	char *bufend = pack_varint32(buf, len);
-	tbuf_append(b, buf, bufend - buf);
-	tbuf_append(b, field, len);
-}
-
-/**
- * Check that we have a valid field and return it.
- * Advances the buffer to point after the field as a side effect.
- */
-const char *
-tbuf_read_field(struct tbuf *buf)
-{
-	const char *field = buf->data;
-	uint32_t field_len = pick_varint32((const char **) &buf->data,
-				      buf->data + buf->size);
-	if (buf->data + field_len > field + buf->size)
-		tnt_raise(IllegalParams, "packet too short (expected a field)");
-	buf->data += field_len;
-	buf->size -= buf->data - field;
-	buf->capacity -= buf->data - field;
-	return field;
-}
-
-static void
-memcached_store(const char *key, uint32_t exptime, uint32_t flags, uint32_t bytes,
-		const char *data)
-{
-	uint32_t box_flags = 0;
-	uint32_t field_count = 4;
-	static uint64_t cas = 42;
-	struct meta m;
-
-	struct tbuf *req = tbuf_new(fiber_ptr->gc_pool);
-
-	tbuf_append(req, &cfg.memcached_space, sizeof(uint32_t));
-	tbuf_append(req, &box_flags, sizeof(box_flags));
-	tbuf_append(req, &field_count, sizeof(field_count));
-
-	tbuf_append_field(req, key);
-
-	m.exptime = exptime;
-	m.flags = flags;
-	m.cas = cas++;
-	tbuf_store_field(req, (const char *) &m, sizeof(m));
-
-	char b[43];
-	sprintf(b, " %" PRIu32 " %" PRIu32 "\r\n", flags, bytes);
-	tbuf_store_field(req, b, strlen(b));
-
-	tbuf_store_field(req, data, bytes);
-
-	int key_len = load_varint32(&key);
-	say_debug("memcached/store key:(%i)'%.*s' exptime:%" PRIu32 " flags:%" PRIu32 " cas:%" PRIu64,
-		  key_len, key_len, (char*) key, exptime, flags, cas);
-	/*
-	 * Use a box dispatch wrapper which handles correctly
-	 * read-only/read-write modes.
-	 */
-	box_process(&null_port, REPLACE, req->data, req->size);
-}
-
-static void
-memcached_delete(const char *key)
-{
-	uint32_t key_len = 1;
-	uint32_t box_flags = 0;
-	struct tbuf *req = tbuf_new(fiber_ptr->gc_pool);
-
-	tbuf_append(req, &cfg.memcached_space, sizeof(uint32_t));
-	tbuf_append(req, &box_flags, sizeof(box_flags));
-	tbuf_append(req, &key_len, sizeof(key_len));
-	tbuf_append_field(req, key);
-
-	box_process(&null_port, DELETE, req->data, req->size);
-}
-
-static struct tuple *
-memcached_find(const char *key)
-{
-	return memcached_index->findByKey(key, 1);
-}
-
-static struct meta *
-memcached_meta(struct tuple *tuple)
-{
-	uint32_t len;
-	const char *field = tuple_field(tuple, 1, &len);
-	assert(sizeof(struct meta) <= len);
-	return (struct meta *) field;
-}
-
-static bool
-memcached_is_expired(struct tuple *tuple)
-{
-	struct meta *m = memcached_meta(tuple);
-	return m->exptime == 0 ? 0 : m->exptime < ev_now();
-}
-
-static bool
-memcached_is_numeric(const char *field, uint32_t value_len)
-{
-	for (int i = 0; i < value_len; i++)
-		if (*(field + i) < '0' || '9' < *(field + i))
-			return false;
-	return true;
-}
-
-static struct stats {
-	uint64_t total_items;
-	uint32_t curr_connections;
-	uint32_t total_connections;
-	uint64_t cmd_get;
-	uint64_t cmd_set;
-	uint64_t get_hits;
-	uint64_t get_misses;
-	uint64_t evictions;
-	uint64_t bytes_read;
-	uint64_t bytes_written;
-} stats;
-
-struct salloc_stat_memcached_cb_ctx {
-	int64_t bytes_used;
-	int64_t items;
-};
-
-static int
-salloc_stat_memcached_cb(const struct slab_cache_stats *cstat, void *cb_ctx)
-{
-	struct salloc_stat_memcached_cb_ctx *ctx =
-			(struct salloc_stat_memcached_cb_ctx *) cb_ctx;
-	ctx->bytes_used	+= cstat->bytes_used;
-	ctx->items	+= cstat->items;
-	return 0;
-}
-
-static void
-memcached_print_stats(struct obuf *out)
-{
-	struct tbuf *buf = tbuf_new(fiber_ptr->gc_pool);
-
-	struct salloc_stat_memcached_cb_ctx memstats;
-	memstats.bytes_used = memstats.items = 0;
-	salloc_stat(salloc_stat_memcached_cb, NULL, &memstats);
-
-	tbuf_printf(buf, "STAT pid %" PRIu32 "\r\n", (uint32_t)getpid());
-	tbuf_printf(buf, "STAT uptime %" PRIu32 "\r\n", (uint32_t)tarantool_uptime());
-	tbuf_printf(buf, "STAT time %" PRIu32 "\r\n", (uint32_t)ev_now());
-	tbuf_printf(buf, "STAT version 1.2.5 (tarantool/box)\r\n");
-	tbuf_printf(buf, "STAT pointer_size %" PRI_SZ "\r\n", sizeof(void *)*8);
-	tbuf_printf(buf, "STAT curr_items %" PRIu64 "\r\n", memstats.items);
-	tbuf_printf(buf, "STAT total_items %" PRIu64 "\r\n", stats.total_items);
-	tbuf_printf(buf, "STAT bytes %" PRIu64 "\r\n", memstats.bytes_used);
-	tbuf_printf(buf, "STAT curr_connections %" PRIu32 "\r\n", stats.curr_connections);
-	tbuf_printf(buf, "STAT total_connections %" PRIu32 "\r\n", stats.total_connections);
-	tbuf_printf(buf, "STAT connection_structures %" PRIu32 "\r\n", stats.curr_connections); /* lie a bit */
-	tbuf_printf(buf, "STAT cmd_get %" PRIu64 "\r\n", stats.cmd_get);
-	tbuf_printf(buf, "STAT cmd_set %" PRIu64 "\r\n", stats.cmd_set);
-	tbuf_printf(buf, "STAT get_hits %" PRIu64 "\r\n", stats.get_hits);
-	tbuf_printf(buf, "STAT get_misses %" PRIu64 "\r\n", stats.get_misses);
-	tbuf_printf(buf, "STAT evictions %" PRIu64 "\r\n", stats.evictions);
-	tbuf_printf(buf, "STAT bytes_read %" PRIu64 "\r\n", stats.bytes_read);
-	tbuf_printf(buf, "STAT bytes_written %" PRIu64 "\r\n", stats.bytes_written);
-	tbuf_printf(buf, "STAT limit_maxbytes %" PRIu64 "\r\n", (uint64_t)(cfg.slab_alloc_arena * (1 << 30)));
-	tbuf_printf(buf, "STAT threads 1\r\n");
-	tbuf_printf(buf, "END\r\n");
-	obuf_dup(out, buf->data, buf->size);
-}
-
-void memcached_get(struct obuf *out, size_t keys_count, struct tbuf *keys,
-		   bool show_cas)
-{
-	stat_collect(stat_base, MEMC_GET, 1);
-	stats.cmd_get++;
-	say_debug("ensuring space for %" PRI_SZ " keys", keys_count);
-	while (keys_count-- > 0) {
-		struct tuple *tuple;
-		const struct meta *m;
-		const char *value;
-		const char *suffix;
-		uint32_t key_len;
-		uint32_t value_len;
-		uint32_t suffix_len;
-
-		const char *key = tbuf_read_field(keys);
-		tuple = memcached_find(key);
-		key_len = load_varint32(&key);
-
-		if (tuple == NULL) {
-			stat_collect(stat_base, MEMC_GET_MISS, 1);
-			stats.get_misses++;
-			continue;
-		}
-
-		uint32_t len;
-		struct tuple_iterator it;
-		tuple_rewind(&it, tuple);
-		/* skip key */
-		(void) tuple_next(&it, &len);
-
-		/* metainfo */
-		m = (const struct meta *) tuple_next(&it, &len);
-		assert(sizeof(struct meta) <= len);
-
-		/* suffix */
-		suffix = tuple_next(&it, &suffix_len);
-
-		/* value */
-		value = tuple_next(&it, &value_len);
-
-		assert(tuple_next(&it, &len) == NULL);
-
-		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);
-
-		if (show_cas) {
-			struct tbuf *b = tbuf_new(fiber_ptr->gc_pool);
-			tbuf_printf(b, "VALUE %.*s %" PRIu32 " %" PRIu32 " %" PRIu64 "\r\n", key_len, (char*) key, m->flags, value_len, m->cas);
-			obuf_dup(out, b->data, b->size);
-			stats.bytes_written += b->size;
-		} else {
-			obuf_dup(out, "VALUE ", 6);
-			obuf_dup(out, key, key_len);
-			obuf_dup(out, suffix, suffix_len);
-		}
-		obuf_dup(out, value, value_len);
-		obuf_dup(out, "\r\n", 2);
-		stats.bytes_written += value_len + 2;
-	}
-	obuf_dup(out, "END\r\n", 5);
-	stats.bytes_written += 5;
-}
-
-static void
-memcached_flush_all(va_list ap)
-{
-	uintptr_t delay = va_arg(ap, uintptr_t);
-	fiber_sleep(delay - ev_now());
-	struct tuple *tuple;
-	struct iterator *it = memcached_index->allocIterator();
-	memcached_index->initIterator(it, ITER_ALL, NULL, 0);
-	while ((tuple = it->next(it))) {
-		memcached_meta(tuple)->exptime = 1;
-	}
-	it->free(it);
-}
-
-#define STORE									\
-do {										\
-	stats.cmd_set++;							\
-	if (bytes > (1<<20)) {							\
-		obuf_dup(out, "SERVER_ERROR object too large for cache\r\n", 41);\
-	} else {								\
-		try {								\
-			memcached_store(key, exptime, flags, bytes, data);	\
-			stats.total_items++;					\
-			obuf_dup(out, "STORED\r\n", 8);				\
-		}								\
-		catch (const ClientError& e) {					\
-			obuf_dup(out, "SERVER_ERROR ", 13);			\
-			obuf_dup(out, e.errmsg(), strlen(e.errmsg()));		\
-			obuf_dup(out, "\r\n", 2);				\
-		}								\
-	}									\
-} while (0)
-
-#include "memcached-grammar.cc"
-
-void
-memcached_loop(struct ev_io *coio, struct iobuf *iobuf)
-{
-	int rc;
-	int bytes_written;
-	int batch_count;
-	struct ibuf *in = &iobuf->in;
-
-	for (;;) {
-		batch_count = 0;
-		if (coio_bread(coio, in, 1) <= 0)
-			return;
-
-	dispatch:
-		rc = memcached_dispatch(coio, iobuf);
-		if (rc < 0) {
-			say_debug("negative dispatch, closing connection");
-			return;
-		}
-
-		if (rc == 0 && batch_count == 0) /* we haven't successfully parsed any requests */
-			continue;
-
-		if (rc == 1) {
-			batch_count++;
-			/* some unparsed commands remain and batch count less than 20 */
-			if (ibuf_size(in) > 0 && batch_count < 20)
-				goto dispatch;
-		}
-
-		bytes_written = iobuf_flush(iobuf, coio);
-		fiber_gc();
-		stats.bytes_written += bytes_written;
-
-		if (rc == 1 && ibuf_size(in) > 0) {
-			batch_count = 0;
-			goto dispatch;
-		}
-	}
-}
-
-static void
-memcached_handler(va_list ap)
-{
-	struct ev_io coio = va_arg(ap, struct ev_io);
-	struct sockaddr_in *addr = va_arg(ap, struct sockaddr_in *);
-	struct iobuf *iobuf = va_arg(ap, struct iobuf *);
-	stats.total_connections++;
-	stats.curr_connections++;
-
-	(void) addr;
-
-	try {
-		auto scoped_guard = make_scoped_guard([&] {
-			fiber_sleep(0.01);
-			stats.curr_connections--;
-			evio_close(&coio);
-			iobuf_delete(iobuf);
-		});
-
-		memcached_loop(&coio, iobuf);
-		iobuf_flush(iobuf, &coio);
-	} catch (const FiberCancelException& e) {
-		throw;
-	} catch (const Exception& e) {
-		e.log();
-	}
-}
-
-int
-memcached_check_config(struct tarantool_cfg *conf)
-{
-	if (conf->memcached_port == 0) {
-		return 0;
-	}
-
-	if (conf->memcached_port <= 0 || conf->memcached_port >= USHRT_MAX) {
-		/* invalid space number */
-		out_warning(CNF_OK, "invalid memcached port value: %i",
-			    conf->memcached_port);
-		return -1;
-	}
-
-	/* check memcached space number: it shoud be in segment [0, max_space] */
-
-	if (conf->memcached_expire_per_loop <= 0) {
-		/* invalid expire per loop value */
-		out_warning(CNF_OK, "invalid expire per loop value: %i",
-			    conf->memcached_expire_per_loop);
-		return -1;
-	}
-
-	if (conf->memcached_expire_full_sweep <= 0) {
-		/* invalid expire full sweep value */
-		out_warning(CNF_OK, "invalid expire full sweep value: %i",
-			    conf->memcached_expire_full_sweep);
-		return -1;
-	}
-
-	return 0;
-}
-
-void
-memcached_free(void)
-{
-	if (memcached_it)
-		memcached_it->free(memcached_it);
-}
-
-
-void
-memcached_init(const char *bind_ipaddr, int memcached_port)
-{
-	if (memcached_port == 0)
-		return;
-
-	stat_base = stat_register(memcached_stat_strs, memcached_stat_MAX);
-
-	struct space *sp = space_by_n(cfg.memcached_space);
-	memcached_index = space_index(sp, 0);
-
-	/* run memcached server */
-	static struct coio_service memcached;
-	coio_service_init(&memcached, "memcached",
-			  bind_ipaddr, memcached_port,
-			  memcached_handler, NULL);
-	evio_service_start(&memcached.evio_service);
-}
-
-void
-memcached_space_init()
-{
-        if (cfg.memcached_port == 0)
-                return;
-
-	/* Configure memcached index key. */
-	struct key_def *key_def = (struct key_def *) malloc(sizeof(struct key_def));
-	key_def->part_count = 1;
-	key_def->is_unique = true;
-	key_def->type = HASH;
-
-	key_def->parts = (struct key_part *) malloc(sizeof(struct key_part));
-	key_def->cmp_order = (uint32_t *) malloc(sizeof(uint32_t));
-
-	key_def->parts[0].fieldno = 0;
-	key_def->parts[0].type = STRING;
-
-	key_def->max_fieldno = 1;
-	key_def->cmp_order[0] = 0;
-
-	(void) space_new(cfg.memcached_space, key_def, 1, 4);
-}
-
-/** Delete a bunch of expired keys. */
-
-void
-memcached_delete_expired_keys(struct tbuf *keys_to_delete)
-{
-	int expired_keys = 0;
-
-	while (keys_to_delete->size > 0) {
-		try {
-			memcached_delete(tbuf_read_field(keys_to_delete));
-			expired_keys++;
-		}
-		catch (const ClientError& e) {
-			/* expire is off when replication is on */
-			assert(e.errcode() != ER_NONMASTER);
-			/* The error is already logged. */
-		}
-	}
-	stat_collect(stat_base, MEMC_EXPIRED_KEYS, expired_keys);
-
-	double delay = ((double) cfg.memcached_expire_per_loop *
-			cfg.memcached_expire_full_sweep /
-			(memcached_index->size() + 1));
-	if (delay > 1)
-		delay = 1;
-	fiber_setcancellable(true);
-	fiber_sleep(delay);
-	fiber_setcancellable(false);
-}
-
-void
-memcached_expire_loop(va_list ap __attribute__((unused)))
-{
-	struct tuple *tuple = NULL;
-
-	say_info("memcached expire fiber started");
-	memcached_it = memcached_index->allocIterator();
-	try {
-restart:
-		if (tuple == NULL)
-			memcached_index->initIterator(memcached_it, ITER_ALL, NULL, 0);
-
-		struct tbuf *keys_to_delete = tbuf_new(fiber_ptr->gc_pool);
-
-		for (int j = 0; j < cfg.memcached_expire_per_loop; j++) {
-
-			tuple = memcached_it->next(memcached_it);
-
-			if (tuple == NULL)
-				break;
-
-			if (!memcached_is_expired(tuple))
-				continue;
-
-			say_debug("expire tuple %p", tuple);
-			uint32_t len = 0;
-			const char *field = tuple_field(tuple, 0, &len);
-			tbuf_store_field(keys_to_delete, field, len);
-		}
-		memcached_delete_expired_keys(keys_to_delete);
-		fiber_gc();
-		goto restart;
-	} catch (const Exception& e) {
-		memcached_it->free(memcached_it);
-		memcached_it = NULL;
-		throw;
-	}
-}
-
-void memcached_start_expire()
-{
-	if (cfg.memcached_port == 0 || cfg.memcached_expire == 0)
-		return;
-
-	assert(memcached_expire == NULL);
-	try {
-		memcached_expire = fiber_new("memcached_expire",
-						memcached_expire_loop);
-	} catch (const Exception& e) {
-		say_error("can't start the expire fiber");
-		return;
-	}
-	fiber_call(memcached_expire);
-}
-
-void memcached_stop_expire()
-{
-	if (cfg.memcached_port == 0 || cfg.memcached_expire == 0)
-		return;
-	assert(memcached_expire != NULL);
-	fiber_cancel(memcached_expire);
-	memcached_expire = NULL;
-}
diff --git a/src/recovery.cc b/src/recovery.cc
deleted file mode 100644
index e2ae5213ac08037968589afa51f8355739fbdd26..0000000000000000000000000000000000000000
--- a/src/recovery.cc
+++ /dev/null
@@ -1,1298 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "recovery.h"
-
-#include <fcntl.h>
-
-#include "log_io.h"
-#include "fiber.h"
-#include "tt_pthread.h"
-#include "fio.h"
-#include "errinj.h"
-
-/*
- * Recovery subsystem
- * ------------------
- *
- * A facade of the recovery subsystem is struct recovery_state,
- * which is a singleton.
- *
- * Depending on the configuration, start-up parameters, the
- * actual task being performed, the recovery can be
- * in a different state.
- *
- * The main factors influencing recovery state are:
- * - temporal: whether or not the instance is just booting
- *   from a snapshot, is in 'local hot standby mode', or
- *   is already accepting requests
- * - topological: whether or not it is a master instance
- *   or a replica
- * - task based: whether it's a master process,
- *   snapshot saving process or a replication relay.
- *
- * Depending on the above factors, recovery can be in two main
- * operation modes: "read mode", recovering in-memory state
- * from existing data, and "write mode", i.e. recording on
- * disk changes of the in-memory state.
- *
- * Let's enumerate all possible distinct states of recovery:
- *
- * Read mode
- * ---------
- * IR - initial recovery, initiated right after server start:
- * reading data from the snapshot and existing WALs
- * and restoring the in-memory state
- * IRR - initial replication relay mode, reading data from
- * existing WALs (xlogs) and sending it to the client.
- *
- * HS - standby mode, entered once all existing WALs are read:
- * following the WAL directory for all changes done by the master
- * and updating the in-memory state
- * RR - replication relay, following the WAL directory for all
- * changes done by the master and sending them to the
- * replica
- *
- * Write mode
- * ----------
- * M - master mode, recording in-memory state changes in the WAL
- * R - replica mode, receiving changes from the master and
- * recording them in the WAL
- * S - snapshot mode, writing entire in-memory state to a compact
- * snapshot file.
- *
- * The following state transitions are possible/supported:
- *
- * recovery_init() -> IR | IRR # recover()
- * IR -> HS         # recovery_follow_local()
- * IRR -> RR        # recovery_follow_local()
- * HS -> M          # recovery_finalize()
- * M -> R           # recovery_follow_remote()
- * R -> M           # recovery_stop_remote()
- * M -> S           # snapshot()
- * R -> S           # snapshot()
- */
-
-struct recovery_state *recovery_state;
-
-static const uint64_t snapshot_cookie = 0;
-
-const char *wal_mode_STRS[] = { "none", "write", "fsync", "fsync_delay", NULL };
-
-/* {{{ LSN API */
-
-void
-wait_lsn_set(struct wait_lsn *wait_lsn, int64_t lsn)
-{
-	assert(wait_lsn->waiter == NULL);
-	wait_lsn->waiter = fiber_ptr;
-	wait_lsn->lsn = lsn;
-}
-
-
-/* Alert the waiter, if any. */
-static inline void
-wakeup_lsn_waiter(struct recovery_state *r)
-{
-	if (r->wait_lsn.waiter && r->confirmed_lsn >= r->wait_lsn.lsn) {
-		fiber_wakeup(r->wait_lsn.waiter);
-	}
-}
-
-void
-confirm_lsn(struct recovery_state *r, int64_t lsn, bool is_commit)
-{
-	assert(r->confirmed_lsn <= r->lsn);
-
-	if (r->confirmed_lsn < lsn) {
-		if (is_commit) {
-			if (r->confirmed_lsn + 1 != lsn)
-				say_warn("non consecutive LSN, confirmed: %jd, "
-					 " new: %jd, diff: %jd",
-					 (intmax_t) r->confirmed_lsn,
-					 (intmax_t) lsn,
-					 (intmax_t) (lsn - r->confirmed_lsn));
-			r->confirmed_lsn = lsn;
-		 }
-	} else {
-		 /*
-		 * There can be holes in
-		 * confirmed_lsn, in case of disk write failure, but
-		 * wal_writer never confirms LSNs out order.
-		 */
-		assert(false);
-		say_error("LSN is used twice or COMMIT order is broken: "
-			  "confirmed: %jd, new: %jd",
-			  (intmax_t) r->confirmed_lsn, (intmax_t) lsn);
-	}
-	wakeup_lsn_waiter(r);
-}
-
-void
-set_lsn(struct recovery_state *r, int64_t lsn)
-{
-	r->lsn = lsn;
-	r->confirmed_lsn = lsn;
-	say_debug("set_lsn(%p, %" PRIi64, r, r->lsn);
-	wakeup_lsn_waiter(r);
-}
-
-/** Wait until the given LSN makes its way to disk. */
-void
-recovery_wait_lsn(struct recovery_state *r, int64_t lsn)
-{
-	while (lsn < r->confirmed_lsn) {
-		wait_lsn_set(&r->wait_lsn, lsn);
-		try {
-			fiber_yield();
-			wait_lsn_clear(&r->wait_lsn);
-		} catch (const Exception& e) {
-			wait_lsn_clear(&r->wait_lsn);
-			throw;
-		}
-	}
-}
-
-
-int64_t
-next_lsn(struct recovery_state *r)
-{
-	r->lsn++;
-	say_debug("next_lsn(%p, %" PRIi64, r, r->lsn);
-	return r->lsn;
-}
-
-
-/* }}} */
-
-/* {{{ Initial recovery */
-
-static int
-wal_writer_start(struct recovery_state *state);
-void
-wal_writer_stop(struct recovery_state *r);
-static void
-recovery_stop_local(struct recovery_state *r);
-
-void
-recovery_init(const char *snap_dirname, const char *wal_dirname,
-	      row_handler row_handler, void *row_handler_param,
-	      int rows_per_wal, int flags)
-{
-	assert(recovery_state == NULL);
-	recovery_state = (struct recovery_state *) p0alloc(eter_pool, sizeof(struct recovery_state));
-	struct recovery_state *r = recovery_state;
-	recovery_update_mode(r, "none", 0);
-
-	assert(rows_per_wal > 1);
-
-	r->row_handler = row_handler;
-	r->row_handler_param = row_handler_param;
-
-	r->snap_dir = &snap_dir;
-	r->snap_dir->dirname = strdup(snap_dirname);
-	r->wal_dir = &wal_dir;
-	r->wal_dir->dirname = strdup(wal_dirname);
-	if (r->wal_mode == WAL_FSYNC) {
-		(void) strcat(r->wal_dir->open_wflags, "s");
-	}
-	r->rows_per_wal = rows_per_wal;
-	wait_lsn_clear(&r->wait_lsn);
-	r->flags = flags;
-}
-
-void
-recovery_update_mode(struct recovery_state *r,
-		     const char *mode, double fsync_delay)
-{
-	r->wal_mode = (enum wal_mode) strindex(wal_mode_STRS, mode, WAL_MODE_MAX);
-	assert(r->wal_mode != WAL_MODE_MAX);
-	/* No mutex lock: let's not bother with whether
-	 * or not a WAL writer thread is present, and
-	 * if it's present, the delay will be propagated
-	 * to it whenever there is a next lock/unlock of
-	 * wal_writer->mutex.
-	 */
-	r->wal_fsync_delay = fsync_delay;
-}
-
-void
-recovery_update_io_rate_limit(struct recovery_state *r, double new_limit)
-{
-	r->snap_io_rate_limit = new_limit * 1024 * 1024;
-	if (r->snap_io_rate_limit == 0)
-		r->snap_io_rate_limit = UINT64_MAX;
-}
-
-void
-recovery_free()
-{
-	struct recovery_state *r = recovery_state;
-	if (r == NULL)
-		return;
-
-	if (r->watcher)
-		recovery_stop_local(r);
-
-	if (r->writer)
-		wal_writer_stop(r);
-
-	free(r->snap_dir->dirname);
-	free(r->wal_dir->dirname);
-	if (r->current_wal) {
-		/*
-		 * Possible if shutting down a replication
-		 * relay or if error during startup.
-		 */
-		log_io_close(&r->current_wal);
-	}
-
-	recovery_state = NULL;
-}
-
-void
-recovery_setup_panic(struct recovery_state *r, bool on_snap_error, bool on_wal_error)
-{
-	r->wal_dir->panic_if_error = on_wal_error;
-	r->snap_dir->panic_if_error = on_snap_error;
-}
-
-
-/**
- * Read a snapshot and call row_handler for every snapshot row.
- * Panic in case of error.
- */
-void
-recover_snap(struct recovery_state *r)
-{
-	/*  current_wal isn't open during initial recover. */
-	assert(r->current_wal == NULL);
-	say_info("recovery start");
-
-	struct log_io *snap;
-	int64_t lsn;
-
-	lsn = greatest_lsn(r->snap_dir);
-	if (lsn <= 0) {
-		say_error("can't find snapshot");
-		goto error;
-	}
-	snap = log_io_open_for_read(r->snap_dir, lsn, NONE);
-	if (snap == NULL) {
-		say_error("can't find/open snapshot");
-		goto error;
-	}
-	say_info("recover from `%s'", snap->filename);
-	struct log_io_cursor i;
-
-	log_io_cursor_open(&i, snap);
-
-	const char *row;
-	uint32_t rowlen;
-	while ((row = log_io_cursor_next(&i, &rowlen))) {
-		if (r->row_handler(r->row_handler_param, row, rowlen) < 0) {
-			say_error("can't apply row");
-			if (snap->dir->panic_if_error)
-				break;
-		}
-	}
-	log_io_cursor_close(&i);
-	log_io_close(&snap);
-
-	if (row == NULL) {
-		r->lsn = r->confirmed_lsn = lsn;
-		say_info("snapshot recovered, confirmed lsn: %"
-			 PRIi64, r->confirmed_lsn);
-		return;
-	}
-error:
-	if (greatest_lsn(r->snap_dir) <= 0) {
-		say_crit("didn't you forget to initialize storage with --init-storage switch?");
-		_exit(1);
-	}
-	panic("snapshot recovery failed");
-}
-
-#define LOG_EOF 0
-
-/**
- * @retval -1 error
- * @retval 0 EOF
- * @retval 1 ok, maybe read something
- */
-static int
-recover_wal(struct recovery_state *r, struct log_io *l)
-{
-	int res = -1;
-	struct log_io_cursor i;
-
-	log_io_cursor_open(&i, l);
-
-	const char *row;
-	uint32_t rowlen;
-	while ((row = log_io_cursor_next(&i, &rowlen))) {
-		int64_t lsn = header_v11(row)->lsn;
-		if (lsn <= r->confirmed_lsn) {
-			say_debug("skipping too young row");
-			continue;
-		}
-		/*
-		 * After handler(row) returned, row may be
-		 * modified, do not use it.
-		 */
-		if (r->row_handler(r->row_handler_param, row, rowlen) < 0) {
-			say_error("can't apply row");
-			if (l->dir->panic_if_error)
-				goto end;
-		}
-		set_lsn(r, lsn);
-	}
-	res = i.eof_read ? LOG_EOF : 1;
-end:
-	log_io_cursor_close(&i);
-	/* Sic: we don't close the log here. */
-	return res;
-}
-
-/** Find out if there are new .xlog files since the current
- * LSN, and read them all up.
- *
- * This function will not close r->current_wal if
- * recovery was successful.
- */
-static int
-recover_remaining_wals(struct recovery_state *r)
-{
-	int result = 0;
-	struct log_io *next_wal;
-	int64_t current_lsn, wal_greatest_lsn;
-	size_t rows_before;
-	FILE *f;
-	char *filename;
-	enum log_suffix suffix;
-
-	current_lsn = r->confirmed_lsn + 1;
-	wal_greatest_lsn = greatest_lsn(r->wal_dir);
-
-	/* if the caller already opened WAL for us, recover from it first */
-	if (r->current_wal != NULL)
-		goto recover_current_wal;
-
-	while (current_lsn <= wal_greatest_lsn) {
-		/*
-		 * If a newer WAL appeared in the directory before
-		 * current_wal was fully read, try re-reading
-		 * one last time. */
-		if (r->current_wal != NULL) {
-			if (r->current_wal->retry++ < 3) {
-				say_warn("`%s' has no EOF marker, yet a newer WAL file exists:"
-					 " trying to re-read (attempt #%d)",
-					 r->current_wal->filename, r->current_wal->retry);
-				goto recover_current_wal;
-			} else {
-				say_warn("WAL `%s' wasn't correctly closed",
-					 r->current_wal->filename);
-				log_io_close(&r->current_wal);
-			}
-		}
-
-		/*
-		 * For the last WAL, first try to open .inprogress
-		 * file: if it doesn't exist, we can safely try an
-		 * .xlog, with no risk of a concurrent
-		 * inprogress_log_rename().
-		 */
-		f = NULL;
-		suffix = INPROGRESS;
-		if (current_lsn == wal_greatest_lsn) {
-			/* Last WAL present at the time of rescan. */
-			filename = format_filename(r->wal_dir,
-						   current_lsn, suffix);
-			f = fopen(filename, "r");
-		}
-		if (f == NULL) {
-			suffix = NONE;
-			filename = format_filename(r->wal_dir,
-						   current_lsn, suffix);
-			f = fopen(filename, "r");
-		}
-		next_wal = log_io_open(r->wal_dir, LOG_READ, filename, suffix, f);
-		/*
-		 * When doing final recovery, and dealing with the
-		 * last file, try opening .<ext>.inprogress.
-		 */
-		if (next_wal == NULL) {
-			if (r->finalize && suffix == INPROGRESS) {
-				/*
-				 * There is an .inprogress file, but
-				 * we failed to open it. Try to
-				 * delete it.
-				 */
-				say_warn("unlink broken %s WAL", filename);
-				if (inprogress_log_unlink(filename) != 0)
-					panic("can't unlink 'inprogres' WAL");
-				result = 0;
-				break;
-			}
-			/* Missing xlog or gap in LSN */
-			say_error("not all WALs have been successfully read");
-			if (!r->wal_dir->panic_if_error) {
-				/* Ignore missing WALs */
-				say_warn("ignoring missing WALs");
-				current_lsn++;
-				continue;
-			}
-			result = -1;
-			break;
-		}
-		assert(r->current_wal == NULL);
-		r->current_wal = next_wal;
-		say_info("recover from `%s'", r->current_wal->filename);
-
-recover_current_wal:
-		rows_before = r->current_wal->rows;
-		result = recover_wal(r, r->current_wal);
-		if (result < 0) {
-			say_error("failure reading from %s",
-				  r->current_wal->filename);
-			break;
-		}
-
-		if (r->current_wal->rows > 0 &&
-		    r->current_wal->rows != rows_before) {
-			r->current_wal->retry = 0;
-		}
-		/* rows == 0 could indicate an empty WAL */
-		if (r->current_wal->rows == 0) {
-			say_error("read zero records from %s",
-				  r->current_wal->filename);
-			break;
-		}
-		if (result == LOG_EOF) {
-			say_info("done `%s' confirmed_lsn: %" PRIi64,
-				 r->current_wal->filename,
-				 r->confirmed_lsn);
-			log_io_close(&r->current_wal);
-		}
-
-		current_lsn = r->confirmed_lsn + 1;
-	}
-
-	/*
-	 * It's not a fatal error when last WAL is empty, but if
-	 * we lose some logs it is a fatal error.
-	 */
-	if (wal_greatest_lsn > r->confirmed_lsn + 1) {
-		say_error("can't recover WALs");
-		result = -1;
-	}
-
-	prelease(fiber_ptr->gc_pool);
-	return result;
-}
-
-/**
- * Recover all WALs created after the last snapshot. Panic if
- * error.
- */
-void
-recover_existing_wals(struct recovery_state *r)
-{
-	int64_t next_lsn = r->confirmed_lsn + 1;
-	int64_t wal_lsn = find_including_file(r->wal_dir, next_lsn);
-	if (wal_lsn <= 0) {
-		/* No WALs to recover from. */
-		goto out;
-	}
-	r->current_wal = log_io_open_for_read(r->wal_dir, wal_lsn, NONE);
-	if (r->current_wal == NULL)
-		goto out;
-	if (recover_remaining_wals(r) < 0)
-		panic("recover failed");
-	say_info("WALs recovered, confirmed lsn: %" PRIi64, r->confirmed_lsn);
-out:
-	prelease(fiber_ptr->gc_pool);
-}
-
-void
-recovery_finalize(struct recovery_state *r)
-{
-	int result;
-
-	if (r->watcher)
-		recovery_stop_local(r);
-
-	r->finalize = true;
-
-	result = recover_remaining_wals(r);
-	if (result < 0)
-		panic("unable to successfully finalize recovery");
-
-	if (r->current_wal != NULL && result != LOG_EOF) {
-		say_warn("WAL `%s' wasn't correctly closed", r->current_wal->filename);
-
-		if (!r->current_wal->is_inprogress) {
-			if (r->current_wal->rows == 0)
-			        /* Regular WAL (not inprogress) must contain at least one row */
-				panic("zero rows was successfully read from last WAL `%s'",
-				      r->current_wal->filename);
-		} else if (r->current_wal->rows == 0) {
-			/* Unlink empty inprogress WAL */
-			say_warn("unlink broken %s WAL", r->current_wal->filename);
-			if (inprogress_log_unlink(r->current_wal->filename) != 0)
-				panic("can't unlink 'inprogress' WAL");
-		} else if (r->current_wal->rows == 1) {
-			/* Rename inprogress wal with one row */
-			say_warn("rename unfinished %s WAL", r->current_wal->filename);
-			if (inprogress_log_rename(r->current_wal) != 0)
-				panic("can't rename 'inprogress' WAL");
-		} else
-			panic("too many rows in inprogress WAL `%s'", r->current_wal->filename);
-
-		log_io_close(&r->current_wal);
-	}
-
-	if ((r->flags & RECOVER_READONLY) == 0)
-		wal_writer_start(r);
-}
-
-
-/* }}} */
-
-/* {{{ Local recovery: support of hot standby and replication relay */
-
-/**
- * This is used in local hot standby or replication
- * relay mode: look for changes in the wal_dir and apply them
- * locally or send to the replica.
- */
-struct wal_watcher {
-	/**
-	 * Rescan the WAL directory in search for new WAL files
-	 * every wal_dir_rescan_delay seconds.
-	 */
-	ev_timer dir_timer;
-	/**
-	 * When the latest WAL does not contain a EOF marker,
-	 * re-read its tail on every change in file metadata.
-	 */
-	ev_stat stat;
-	/** Path to the file being watched with 'stat'. */
-	char filename[PATH_MAX+1];
-};
-
-static struct wal_watcher wal_watcher;
-
-static void recovery_rescan_file(ev_stat *w, int revents __attribute__((unused)));
-
-static void
-recovery_watch_file(struct wal_watcher *watcher, struct log_io *wal)
-{
-	strncpy(watcher->filename, wal->filename, PATH_MAX);
-	ev_stat_init(&watcher->stat, recovery_rescan_file, watcher->filename, 0.);
-	ev_stat_start(&watcher->stat);
-}
-
-static void
-recovery_stop_file(struct wal_watcher *watcher)
-{
-	ev_stat_stop(&watcher->stat);
-}
-
-static void
-recovery_rescan_dir(ev_timer *w, int revents __attribute__((unused)))
-{
-	struct recovery_state *r = (struct recovery_state *) w->data;
-	struct wal_watcher *watcher = r->watcher;
-	struct log_io *save_current_wal = r->current_wal;
-
-	int result = recover_remaining_wals(r);
-	if (result < 0)
-		panic("recover failed: %i", result);
-	if (save_current_wal != r->current_wal) {
-		if (save_current_wal != NULL)
-			recovery_stop_file(watcher);
-		if (r->current_wal != NULL)
-			recovery_watch_file(watcher, r->current_wal);
-	}
-}
-
-static void
-recovery_rescan_file(ev_stat *w, int revents __attribute__((unused)))
-{
-	struct recovery_state *r = (struct recovery_state *) w->data;
-	struct wal_watcher *watcher = r->watcher;
-	int result = recover_wal(r, r->current_wal);
-	if (result < 0)
-		panic("recover failed");
-	if (result == LOG_EOF) {
-		say_info("done `%s' confirmed_lsn: %" PRIi64,
-			 r->current_wal->filename,
-			 r->confirmed_lsn);
-		log_io_close(&r->current_wal);
-		recovery_stop_file(watcher);
-		/* Don't wait for wal_dir_rescan_delay. */
-		recovery_rescan_dir(&watcher->dir_timer, 0);
-	}
-}
-
-void
-recovery_follow_local(struct recovery_state *r, ev_tstamp wal_dir_rescan_delay)
-{
-	assert(r->watcher == NULL);
-	assert(r->writer == NULL);
-
-	struct wal_watcher  *watcher = r->watcher= &wal_watcher;
-
-	ev_timer_init(&watcher->dir_timer, recovery_rescan_dir,
-		      wal_dir_rescan_delay, wal_dir_rescan_delay);
-	watcher->dir_timer.data = watcher->stat.data = r;
-	ev_timer_start(&watcher->dir_timer);
-	/*
-	 * recover() leaves the current wal open if it has no
-	 * EOF marker.
-	 */
-	if (r->current_wal != NULL)
-		recovery_watch_file(watcher, r->current_wal);
-}
-
-static void
-recovery_stop_local(struct recovery_state *r)
-{
-	struct wal_watcher *watcher = r->watcher;
-	assert(ev_is_active(&watcher->dir_timer));
-	ev_timer_stop(&watcher->dir_timer);
-	if (ev_is_active(&watcher->stat))
-		ev_stat_stop(&watcher->stat);
-
-	r->watcher = NULL;
-}
-
-/* }}} */
-
-/* {{{ WAL writer - maintain a Write Ahead Log for every change
- * in the data state.
- */
-
-struct wal_write_request {
-	STAILQ_ENTRY(wal_write_request) wal_fifo_entry;
-	/* Auxiliary. */
-	int res;
-	struct fiber *fiber;
-	struct row_v11 row;
-};
-
-/* Context of the WAL writer thread. */
-STAILQ_HEAD(wal_fifo, wal_write_request);
-
-struct wal_writer
-{
-	struct wal_fifo input;
-	struct wal_fifo commit;
-	pthread_t thread;
-	pthread_mutex_t mutex;
-	pthread_cond_t cond;
-	ev_async write_event;
-	struct fio_batch *batch;
-	bool is_shutdown;
-	bool is_rollback;
-};
-
-static pthread_once_t wal_writer_once = PTHREAD_ONCE_INIT;
-
-static struct wal_writer wal_writer;
-
-/**
- * A pthread_atfork() callback for a child process. Today we only
- * fork the master process to save a snapshot, and in the child
- * the WAL writer thread is not necessary and not present.
- */
-static void
-wal_writer_child()
-{
-	log_io_atfork(&recovery_state->current_wal);
-	if (wal_writer.batch) {
-		free(wal_writer.batch);
-		wal_writer.batch = NULL;
-	}
-	/*
-	 * Make sure that atexit() handlers in the child do
-	 * not try to stop the non-existent thread.
-	 * The writer is not used in the child.
-	 */
-	recovery_state->writer = NULL;
-}
-
-/**
- * Today a WAL writer is started once at start of the
- * server.  Nevertheless, use pthread_once() to make
- * sure we can start/stop the writer many times.
- */
-static void
-wal_writer_init_once()
-{
-	(void) tt_pthread_atfork(NULL, NULL, wal_writer_child);
-}
-
-/**
- * A commit watcher callback is invoked whenever there
- * are requests in wal_writer->commit. This callback is
- * associated with an internal WAL writer watcher and is
- * invoked in the front-end main event loop.
- *
- * A rollback watcher callback is invoked only when there is
- * a rollback request and commit is empty.
- * We roll back the entire input queue.
- *
- * ev_async, under the hood, is a simple pipe. The WAL
- * writer thread writes to that pipe whenever it's done
- * handling a pack of requests (look for ev_async_send()
- * call in the writer thread loop).
- */
-static void
-wal_schedule_queue(struct wal_fifo *queue)
-{
-	/*
-	 * Can't use STAILQ_FOREACH since fiber_call()
-	 * destroys the list entry.
-	 */
-	struct wal_write_request *req, *tmp;
-	STAILQ_FOREACH_SAFE(req, queue, wal_fifo_entry, tmp)
-		fiber_call(req->fiber);
-}
-
-static void
-wal_schedule(ev_async *watcher, int event __attribute__((unused)))
-{
-	struct wal_writer *writer = (struct wal_writer *) watcher->data;
-	struct wal_fifo commit = STAILQ_HEAD_INITIALIZER(commit);
-	struct wal_fifo rollback = STAILQ_HEAD_INITIALIZER(rollback);
-
-	(void) tt_pthread_mutex_lock(&writer->mutex);
-	STAILQ_CONCAT(&commit, &writer->commit);
-	if (writer->is_rollback) {
-		STAILQ_CONCAT(&rollback, &writer->input);
-		writer->is_rollback = false;
-	}
-	(void) tt_pthread_mutex_unlock(&writer->mutex);
-
-	wal_schedule_queue(&commit);
-	/*
-	 * Perform a cascading abort of all transactions which
-	 * depend on the transaction which failed to get written
-	 * to the write ahead log. Abort transactions
-	 * in reverse order, performing a playback of the
-	 * in-memory database state.
-	 */
-	STAILQ_REVERSE(&rollback, wal_write_request, wal_fifo_entry);
-	wal_schedule_queue(&rollback);
-}
-
-/**
- * Initialize WAL writer context. Even though it's a singleton,
- * encapsulate the details just in case we may use
- * more writers in the future.
- */
-static void
-wal_writer_init(struct wal_writer *writer)
-{
-	/* I. Initialize the state. */
-	pthread_mutexattr_t errorcheck;
-
-	(void) tt_pthread_mutexattr_init(&errorcheck);
-
-#ifndef NDEBUG
-	(void) tt_pthread_mutexattr_settype(&errorcheck, PTHREAD_MUTEX_ERRORCHECK);
-#endif
-	/* Initialize queue lock mutex. */
-	(void) tt_pthread_mutex_init(&writer->mutex, &errorcheck);
-	(void) tt_pthread_mutexattr_destroy(&errorcheck);
-
-	(void) tt_pthread_cond_init(&writer->cond, NULL);
-
-	STAILQ_INIT(&writer->input);
-	STAILQ_INIT(&writer->commit);
-
-	ev_async_init(&writer->write_event, wal_schedule);
-	writer->write_event.data = writer;
-
-	(void) tt_pthread_once(&wal_writer_once, wal_writer_init_once);
-
-	writer->batch = fio_batch_alloc(sysconf(_SC_IOV_MAX));
-
-	if (writer->batch == NULL)
-		panic_syserror("fio_batch_alloc");
-}
-
-/** Destroy a WAL writer structure. */
-static void
-wal_writer_destroy(struct wal_writer *writer)
-{
-	(void) tt_pthread_mutex_destroy(&writer->mutex);
-	(void) tt_pthread_cond_destroy(&writer->cond);
-	free(writer->batch);
-}
-
-/** WAL writer thread routine. */
-static void *wal_writer_thread(void *worker_args);
-
-/**
- * Initialize WAL writer, start the thread.
- *
- * @pre   The server has completed recovery from a snapshot
- *        and/or existing WALs. All WALs opened in read-only
- *        mode are closed.
- *
- * @param state			WAL writer meta-data.
- *
- * @return 0 success, -1 on error. On success, recovery->writer
- *         points to a newly created WAL writer.
- */
-static int
-wal_writer_start(struct recovery_state *r)
-{
-	assert(r->writer == NULL);
-	assert(r->watcher == NULL);
-	assert(r->current_wal == NULL);
-	assert(! wal_writer.is_shutdown);
-	assert(STAILQ_EMPTY(&wal_writer.input));
-	assert(STAILQ_EMPTY(&wal_writer.commit));
-
-	/* I. Initialize the state. */
-	wal_writer_init(&wal_writer);
-	r->writer = &wal_writer;
-
-	ev_async_start(&wal_writer.write_event);
-
-	/* II. Start the thread. */
-
-	if (tt_pthread_create(&wal_writer.thread, NULL, wal_writer_thread, r)) {
-		wal_writer_destroy(&wal_writer);
-		r->writer = NULL;
-		return -1;
-	}
-	return 0;
-}
-
-/** Stop and destroy the writer thread (at shutdown). */
-void
-wal_writer_stop(struct recovery_state *r)
-{
-	struct wal_writer *writer = r->writer;
-
-	/* Stop the worker thread. */
-
-	(void) tt_pthread_mutex_lock(&writer->mutex);
-	writer->is_shutdown= true;
-	(void) tt_pthread_cond_signal(&writer->cond);
-	(void) tt_pthread_mutex_unlock(&writer->mutex);
-
-	if (tt_pthread_join(writer->thread, NULL) != 0) {
-		/* We can't recover from this in any reasonable way. */
-		panic_syserror("WAL writer: thread join failed");
-	}
-
-	ev_async_stop(&writer->write_event);
-	wal_writer_destroy(writer);
-
-	r->writer = NULL;
-}
-
-/**
- * Pop a bulk of requests to write to disk to process.
- * Block on the condition only if we have no other work to
- * do. Loop in case of a spurious wakeup.
- */
-void
-wal_writer_pop(struct wal_writer *writer, struct wal_fifo *input)
-{
-	while (! writer->is_shutdown)
-	{
-		if (! writer->is_rollback && ! STAILQ_EMPTY(&writer->input)) {
-			STAILQ_CONCAT(input, &writer->input);
-			break;
-		}
-		(void) tt_pthread_cond_wait(&writer->cond, &writer->mutex);
-	}
-}
-
-/**
- * If there is no current WAL, try to open it, and close the
- * previous WAL. We close the previous WAL only after opening
- * a new one to smoothly move local hot standby and replication
- * over to the next WAL.
- * If the current WAL has only 1 record, it means we need to
- * rename it from '.inprogress' to '.xlog'. We maintain
- * '.inprogress' WALs to ensure that, at any point in time,
- * an .xlog file contains at least 1 valid record.
- * In case of error, we try to close any open WALs.
- *
- * @post r->current_wal is in a good shape for writes or is NULL.
- * @return 0 in case of success, -1 on error.
- */
-static int
-wal_opt_rotate(struct log_io **wal, int rows_per_wal, struct log_dir *dir,
-	       int64_t lsn)
-{
-	struct log_io *l = *wal, *wal_to_close = NULL;
-
-	ERROR_INJECT_RETURN(ERRINJ_WAL_ROTATE);
-
-	if (l != NULL && (l->rows >= rows_per_wal || lsn % rows_per_wal == 0)) {
-		/*
-		 * if l->rows == 1, log_io_close() does
-		 * inprogress_log_rename() for us.
-		 */
-		wal_to_close = l;
-		l = NULL;
-	}
-	if (l == NULL) {
-		/* Open WAL with '.inprogress' suffix. */
-		l = log_io_open_for_write(dir, lsn, INPROGRESS);
-		/*
-		 * Close the file *after* we create the new WAL, since
-		 * this is when replication relays get an inotify alarm
-		 * (when we close the file), and try to reopen the next
-		 * WAL. In other words, make sure that replication relays
-		 * try to open the next WAL only when it exists.
-		 */
-		if (wal_to_close) {
-			/*
-			 * We can not handle log_io_close()
-			 * failure in any reasonable way.
-			 * A warning is written to the server
-			 * log file.
-			 */
-			log_io_close(&wal_to_close);
-		}
-	} else if (l->rows == 1) {
-		/*
-		 * Rename WAL after the first successful write
-		 * to a name  without .inprogress suffix.
-		 */
-		if (inprogress_log_rename(l))
-			log_io_close(&l);       /* error. */
-	}
-	assert(wal_to_close == NULL);
-	*wal = l;
-	return l ? 0 : -1;
-}
-
-static void
-wal_opt_sync(struct log_io *wal, double sync_delay)
-{
-	static ev_tstamp last_sync = 0;
-
-	if (sync_delay > 0 && ev_now() - last_sync >= sync_delay) {
-		/*
-		 * XXX: in case of error, we don't really know how
-		 * many records were not written to disk: probably
-		 * way more than the last one.
-		 */
-		(void) log_io_sync(wal);
-		last_sync = ev_now();
-	}
-}
-
-static struct wal_write_request *
-wal_fill_batch(struct log_io *wal, struct fio_batch *batch, int rows_per_wal,
-	       struct wal_write_request *req)
-{
-	int max_rows = wal->is_inprogress ? 1 : rows_per_wal - wal->rows;
-	/* Post-condition of successful wal_opt_rotate(). */
-	assert(max_rows > 0);
-	fio_batch_start(batch, max_rows);
-	while (req != NULL && ! fio_batch_is_full(batch)) {
-		struct row_v11 *row = &req->row;
-		header_v11_sign(&row->header);
-		fio_batch_add(batch, row, row_v11_size(row));
-		req = STAILQ_NEXT(req, wal_fifo_entry);
-	}
-	return req;
-}
-
-static struct wal_write_request *
-wal_write_batch(struct log_io *wal, struct fio_batch *batch,
-		struct wal_write_request *req, struct wal_write_request *end)
-{
-	int rows_written = fio_batch_write(batch, fileno(wal->f));
-	wal->rows += rows_written;
-	while (req != end && rows_written-- != 0)  {
-		req->res = 0;
-		req = STAILQ_NEXT(req, wal_fifo_entry);
-	}
-	return req;
-}
-
-static void
-wal_write_to_disk(struct recovery_state *r, struct wal_writer *writer,
-		  struct wal_fifo *input, struct wal_fifo *commit,
-		  struct wal_fifo *rollback)
-{
-	struct log_io **wal = &r->current_wal;
-	struct fio_batch *batch = writer->batch;
-
-	struct wal_write_request *req = STAILQ_FIRST(input);
-	struct wal_write_request *write_end = req;
-
-	while (req) {
-		if (wal_opt_rotate(wal, r->rows_per_wal, r->wal_dir,
-				   req->row.header.lsn) != 0)
-			break;
-		struct wal_write_request *batch_end;
-		batch_end = wal_fill_batch(*wal, batch, r->rows_per_wal, req);
-		write_end = wal_write_batch(*wal, batch, req, batch_end);
-		if (batch_end != write_end)
-			break;
-		wal_opt_sync(*wal, r->wal_fsync_delay);
-		req = write_end;
-	}
-	STAILQ_SPLICE(input, write_end, wal_fifo_entry, rollback);
-	STAILQ_CONCAT(commit, input);
-}
-
-/** WAL writer thread main loop.  */
-static void *
-wal_writer_thread(void *worker_args)
-{
-	struct recovery_state *r = (struct recovery_state *) worker_args;
-	struct wal_writer *writer = r->writer;
-	struct wal_fifo input = STAILQ_HEAD_INITIALIZER(input);
-	struct wal_fifo commit = STAILQ_HEAD_INITIALIZER(commit);
-	struct wal_fifo rollback = STAILQ_HEAD_INITIALIZER(rollback);
-
-	(void) tt_pthread_mutex_lock(&writer->mutex);
-	while (! writer->is_shutdown) {
-		wal_writer_pop(writer, &input);
-		(void) tt_pthread_mutex_unlock(&writer->mutex);
-
-		wal_write_to_disk(r, writer, &input, &commit, &rollback);
-
-		(void) tt_pthread_mutex_lock(&writer->mutex);
-		STAILQ_CONCAT(&writer->commit, &commit);
-		if (! STAILQ_EMPTY(&rollback)) {
-			/*
-			 * Begin rollback: create a rollback queue
-			 * from all requests which were not
-			 * written to disk and all requests in the
-			 * input queue.
-			 */
-			writer->is_rollback = true;
-			STAILQ_CONCAT(&rollback, &writer->input);
-			STAILQ_CONCAT(&writer->input, &rollback);
-		}
-		ev_async_send(&writer->write_event);
-	}
-	(void) tt_pthread_mutex_unlock(&writer->mutex);
-	if (r->current_wal != NULL)
-		log_io_close(&r->current_wal);
-	return NULL;
-}
-
-/**
- * WAL writer main entry point: queue a single request
- * to be written to disk and wait until this task is completed.
- */
-int
-wal_write(struct recovery_state *r, int64_t lsn, uint64_t cookie,
-	  uint16_t op, const char *row, uint32_t row_len)
-{
-	say_debug("wal_write lsn=%" PRIi64, lsn);
-	ERROR_INJECT_RETURN(ERRINJ_WAL_IO);
-
-	if (r->wal_mode == WAL_NONE)
-		return 0;
-
-	struct wal_writer *writer = r->writer;
-
-	struct wal_write_request *req = (struct wal_write_request *)
-		palloc(fiber_ptr->gc_pool, sizeof(struct wal_write_request) +
-		       sizeof(op) + row_len);
-
-	req->fiber = fiber_ptr;
-	req->res = -1;
-	row_v11_fill(&req->row, lsn, XLOG, cookie, (const char *) &op,
-		     sizeof(op), row, row_len);
-
-	(void) tt_pthread_mutex_lock(&writer->mutex);
-
-	bool input_was_empty = STAILQ_EMPTY(&writer->input);
-	STAILQ_INSERT_TAIL(&writer->input, req, wal_fifo_entry);
-
-	if (input_was_empty)
-		(void) tt_pthread_cond_signal(&writer->cond);
-
-	(void) tt_pthread_mutex_unlock(&writer->mutex);
-
-	fiber_yield(); /* Request was inserted. */
-
-	return req->res;
-}
-
-/* }}} */
-
-/* {{{ SAVE SNAPSHOT and tarantool_box --cat */
-
-void
-snapshot_write_row(struct log_io *l,
-		   const char *metadata, size_t metadata_len,
-		   const char *data, size_t data_len)
-{
-	static uint64_t bytes;
-	ev_tstamp elapsed;
-	static ev_tstamp last = 0;
-
-	struct row_v11 *row = (struct row_v11 *) palloc(fiber_ptr->gc_pool,
-				     sizeof(struct row_v11) +
-				     data_len + metadata_len);
-
-	row_v11_fill(row, 0, SNAP, snapshot_cookie,
-		     metadata, metadata_len, data, data_len);
-	header_v11_sign(&row->header);
-
-
-	size_t written = fwrite(row, 1, row_v11_size(row), l->f);
-
-	if (written != row_v11_size(row)) {
-		say_error("Can't write row (%zu bytes)", row_v11_size(row));
-		panic_syserror("snapshot_write_row");
-	}
-
-	bytes += written;
-
-
-	prelease_after(fiber_ptr->gc_pool, 128 * 1024);
-
-	if (recovery_state->snap_io_rate_limit != UINT64_MAX) {
-		if (last == 0) {
-			/*
-			 * Remember the time of first
-			 * write to disk.
-			 */
-			ev_now_update();
-			last = ev_now();
-		}
-		/**
-		 * If io rate limit is set, flush the
-		 * filesystem cache, otherwise the limit is
-		 * not really enforced.
-		 */
-		if (bytes > recovery_state->snap_io_rate_limit)
-			fdatasync(fileno(l->f));
-	}
-	while (bytes > recovery_state->snap_io_rate_limit) {
-		ev_now_update();
-		/*
-		 * How much time have passed since
-		 * last write?
-		 */
-		elapsed = ev_now() - last;
-		/*
-		 * If last write was in less than
-		 * a second, sleep until the
-		 * second is reached.
-		 */
-		if (elapsed < 1)
-			usleep(((1 - elapsed) * 1000000));
-
-		ev_now_update();
-		last = ev_now();
-		bytes -= recovery_state->snap_io_rate_limit;
-	}
-}
-
-void
-snapshot_save(struct recovery_state *r, void (*f) (struct log_io *))
-{
-	struct log_io *snap;
-	snap = log_io_open_for_write(r->snap_dir, r->confirmed_lsn,
-				     INPROGRESS);
-	if (snap == NULL)
-		panic_status(errno, "Failed to save snapshot: failed to open file in write mode.");
-	/*
-	 * While saving a snapshot, snapshot name is set to
-	 * <lsn>.snap.inprogress. When done, the snapshot is
-	 * renamed to <lsn>.snap.
-	 */
-	say_info("saving snapshot `%s'",
-		 format_filename(r->snap_dir, r->confirmed_lsn,
-				 NONE));
-	if (f)
-		f(snap);
-
-	log_io_close(&snap);
-
-	say_info("done");
-}
-
-/**
- * Read WAL/SNAPSHOT and invoke a callback on every record (used
- * for --cat command line option).
- * @retval 0  success
- * @retval -1 error
- */
-
-int
-read_log(const char *filename,
-	 row_handler *xlog_handler, row_handler *snap_handler,
-	 void *param)
-{
-	struct log_dir *dir;
-	row_handler *h;
-
-	if (strstr(filename, wal_dir.filename_ext)) {
-		dir = &wal_dir;
-		h = xlog_handler;
-	} else if (strstr(filename, snap_dir.filename_ext)) {
-		dir = &snap_dir;
-		h = snap_handler;
-	} else {
-		say_error("don't know how to read `%s'", filename);
-		return -1;
-	}
-
-	FILE *f = fopen(filename, "r");
-	struct log_io *l = log_io_open(dir, LOG_READ, filename, NONE, f);
-	if (l == NULL)
-		return -1;
-
-	struct log_io_cursor i;
-
-	log_io_cursor_open(&i, l);
-	const char *row;
-	uint32_t rowlen;
-	while ((row = log_io_cursor_next(&i, &rowlen)))
-		h(param, row, rowlen);
-
-	log_io_cursor_close(&i);
-	log_io_close(&l);
-	return 0;
-}
-
-/* }}} */
-
diff --git a/src/replica.cc b/src/replica.cc
deleted file mode 100644
index 4860fe39e5cd1349c28f93f8697436135f0016d8..0000000000000000000000000000000000000000
--- a/src/replica.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "recovery.h"
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "log_io.h"
-#include "fiber.h"
-#include "pickle.h"
-#include "coio_buf.h"
-#include "tarantool.h"
-
-static void
-remote_apply_row(struct recovery_state *r, const char *row, uint32_t rowlne);
-
-const char *
-remote_read_row(struct ev_io *coio, struct iobuf *iobuf, uint32_t *rowlen)
-{
-	struct ibuf *in = &iobuf->in;
-	ssize_t to_read = sizeof(struct header_v11) - ibuf_size(in);
-
-	if (to_read > 0) {
-		ibuf_reserve(in, cfg_readahead);
-		coio_breadn(coio, in, to_read);
-	}
-
-	ssize_t request_len = header_v11(in->pos)->len
-		+ sizeof(struct header_v11);
-	to_read = request_len - ibuf_size(in);
-
-	if (to_read > 0)
-		coio_breadn(coio, in, to_read);
-
-	const char *row = in->pos;
-	*rowlen = request_len;
-	in->pos += request_len;
-	return row;
-}
-
-static void
-remote_connect(struct ev_io *coio, struct sockaddr_in *remote_addr,
-	       int64_t initial_lsn, const char **err)
-{
-	evio_socket(coio, AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
-	*err = "can't connect to master";
-	coio_connect(coio, remote_addr);
-
-	*err = "can't write version";
-	coio_write(coio, &initial_lsn, sizeof(initial_lsn));
-
-	uint32_t version;
-	*err = "can't read version";
-	coio_readn(coio, &version, sizeof(version));
-	*err = NULL;
-	if (version != default_version)
-		tnt_raise(IllegalParams, "remote version mismatch");
-
-	say_crit("successfully connected to master");
-	say_crit("starting replication from lsn: %" PRIi64, initial_lsn);
-}
-
-static void
-pull_from_remote(va_list ap)
-{
-	struct recovery_state *r = va_arg(ap, struct recovery_state *);
-	struct ev_io coio;
-	struct iobuf *iobuf = NULL;
-	bool warning_said = false;
-	const int reconnect_delay = 1;
-
-	coio_init(&coio);
-
-	for (;;) {
-		const char *err = NULL;
-		try {
-			fiber_setcancellable(true);
-			if (! evio_is_active(&coio)) {
-				title("replica", "%s/%s", r->remote->source,
-				      "connecting");
-				if (iobuf == NULL)
-					iobuf = iobuf_new(fiber_name(fiber_ptr));
-				remote_connect(&coio, &r->remote->addr,
-					       r->confirmed_lsn + 1, &err);
-				warning_said = false;
-				title("replica", "%s/%s", r->remote->source,
-				      "connected");
-			}
-			err = "can't read row";
-			uint32_t rowlen;
-			const char *row = remote_read_row(&coio, iobuf, &rowlen);
-			fiber_setcancellable(false);
-			err = NULL;
-
-			r->remote->recovery_lag = ev_now() - header_v11(row)->tm;
-			r->remote->recovery_last_update_tstamp = ev_now();
-
-			remote_apply_row(r, row, rowlen);
-
-			iobuf_gc(iobuf);
-			fiber_gc();
-		} catch (const FiberCancelException& e) {
-			title("replica", "%s/%s", r->remote->source, "failed");
-			iobuf_delete(iobuf);
-			evio_close(&coio);
-			throw;
-		} catch (const Exception& e) {
-			title("replica", "%s/%s", r->remote->source, "failed");
-			e.log();
-			if (! warning_said) {
-				if (err != NULL)
-					say_info("%s", err);
-				say_info("will retry every %i second", reconnect_delay);
-				warning_said = true;
-			}
-			evio_close(&coio);
-		}
-
-		/* Put fiber_sleep() out of catch block.
-		 *
-		 * This is done to avoid situation, when two or more
-		 * fibers yield's inside their try/catch blocks and
-		 * throws an exceptions. Seems like exception unwinder
-		 * stores some global state while being inside a catch
-		 * block.
-		 *
-		 * This could lead to incorrect exception processing
-		 * and crash the server.
-		 *
-		 * See: https://github.com/tarantool/tarantool/issues/136
-		*/
-		if (! evio_is_active(&coio))
-			fiber_sleep(reconnect_delay);
-	}
-}
-
-static void
-remote_apply_row(struct recovery_state *r, const char *row, uint32_t rowlen)
-{
-	int64_t lsn = header_v11(row)->lsn;
-
-	assert(*(uint16_t*)(row + sizeof(struct header_v11)) == XLOG);
-
-	if (r->row_handler(r->row_handler_param, row, rowlen) < 0)
-		panic("replication failure: can't apply row");
-
-	set_lsn(r, lsn);
-}
-
-void
-recovery_follow_remote(struct recovery_state *r, const char *addr)
-{
-	char name[FIBER_NAME_MAXLEN];
-	char ip_addr[32];
-	int port;
-	int rc;
-	struct fiber *f;
-	struct in_addr server;
-
-	assert(r->remote == NULL);
-
-	say_crit("initializing the replica, WAL master %s", addr);
-	snprintf(name, sizeof(name), "replica/%s", addr);
-
-	try {
-		f = fiber_new(name, pull_from_remote);
-	} catch (const Exception& ) {
-		return;
-	}
-
-	rc = sscanf(addr, "%31[^:]:%i", ip_addr, &port);
-	assert(rc == 2);
-	(void)rc;
-
-	if (inet_aton(ip_addr, &server) < 0) {
-		say_syserror("inet_aton: %s", ip_addr);
-		return;
-	}
-
-	static struct remote remote;
-	memset(&remote, 0, sizeof(remote));
-	remote.addr.sin_family = AF_INET;
-	memcpy(&remote.addr.sin_addr.s_addr, &server, sizeof(server));
-	remote.addr.sin_port = htons(port);
-	memcpy(&remote.cookie, &remote.addr, MIN(sizeof(remote.cookie), sizeof(remote.addr)));
-	remote.reader = f;
-	snprintf(remote.source, sizeof(remote.source), "%s", addr);
-	r->remote = &remote;
-	fiber_call(f, r);
-}
-
-void
-recovery_stop_remote(struct recovery_state *r)
-{
-	say_info("shutting down the replica");
-	fiber_cancel(r->remote->reader);
-	r->remote = NULL;
-}
diff --git a/src/replication.cc b/src/replication.cc
deleted file mode 100644
index 41d71c65b3fa91cab450227dc9f62ab3b4a8ff50..0000000000000000000000000000000000000000
--- a/src/replication.cc
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <replication.h>
-#include <say.h>
-#include <fiber.h>
-extern "C" {
-#include <cfg/warning.h>
-#include <cfg/tarantool_box_cfg.h>
-} /* extern "C" */
-#include <palloc.h>
-#include <stddef.h>
-
-#include <stddef.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <sys/uio.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <limits.h>
-#include <fcntl.h>
-
-#include "fiber.h"
-#include "recovery.h"
-#include "log_io.h"
-#include "evio.h"
-
-/** Replication topology
- * ----------------------
- *
- * Tarantool replication consists of 3 interacting processes:
- * master, spawner and replication relay.
- *
- * The spawner is created at server start, and master communicates
- * with the spawner using a socketpair(2). Replication relays are
- * created by the spawner and handle one client connection each.
- *
- * The master process binds to replication_port and accepts
- * incoming connections. This is done in the master to be able to
- * correctly handle RELOAD CONFIGURATION, which happens in the
- * master, and, in future, perform authentication of replication
- * clients.
- *
- * Once a client socket is accepted, it is sent to the spawner
- * process, through the master's end of the socket pair.
- *
- * The spawner listens on the receiving end of the socket pair and
- * for every received socket creates a replication relay, which is
- * then responsible for sending write ahead logs to the replica.
- *
- * Upon shutdown, the master closes its end of the socket pair.
- * The spawner then reads EOF from its end, terminates all
- * children and exits.
- */
-static int master_to_spawner_socket;
-
-/** Accept a new connection on the replication port: push the accepted socket
- * to the spawner.
- */
-static void
-replication_on_accept(struct evio_service *service __attribute__((unused)),
-		      int fd, struct sockaddr_in *addr __attribute__((unused)));
-
-/** Send a file descriptor to replication relay spawner.
- *
- * Invoked when spawner's end of the socketpair becomes ready.
- */
-static void
-replication_send_socket(ev_io *watcher, int events __attribute__((unused)));
-
-/** Replication spawner process */
-static struct spawner {
-	/** reading end of the socket pair with the master */
-	int sock;
-	/** non-zero if got a terminating signal */
-	sig_atomic_t killed;
-	/** child process count */
-	sig_atomic_t child_count;
-} spawner;
-
-/** Initialize spawner process.
- *
- * @param sock the socket between the main process and the spawner.
- */
-static void
-spawner_init(int sock);
-
-/** Spawner main loop. */
-static void
-spawner_main_loop();
-
-/** Shutdown spawner and all its children. */
-static void
-spawner_shutdown();
-
-/** Handle SIGINT, SIGTERM, SIGHUP. */
-static void
-spawner_signal_handler(int signal);
-
-/** Handle SIGCHLD: collect status of a terminated child.  */
-static void
-spawner_sigchld_handler(int signal __attribute__((unused)));
-
-/** Create a replication relay.
- *
- * @return 0 on success, -1 on error
- */
-static int
-spawner_create_replication_relay(int client_sock);
-
-/** Shut down all relays when shutting down the spawner. */
-static void
-spawner_shutdown_children();
-
-/** Initialize replication relay process. */
-static void
-replication_relay_loop(int client_sock);
-
-/*
- * ------------------------------------------------------------------------
- * replication module
- * ------------------------------------------------------------------------
- */
-
-/** Check replication module configuration. */
-int
-replication_check_config(struct tarantool_cfg *config)
-{
-	if (config->replication_port < 0 ||
-	    config->replication_port >= USHRT_MAX) {
-		say_error("invalid replication port value: %" PRId32,
-			  config->replication_port);
-		return -1;
-	}
-
-	return 0;
-}
-
-/** Pre-fork replication spawner process. */
-void
-replication_prefork()
-{
-	if (cfg.replication_port == 0) {
-		/* replication is not needed, do nothing */
-		return;
-	}
-	int sockpair[2];
-	/*
-	 * Create UNIX sockets to communicate between the main and
-	 * spawner processes.
-         */
-	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sockpair) != 0)
-		panic_syserror("socketpair");
-
-	/* create spawner */
-	pid_t pid = fork();
-	if (pid == -1)
-		panic_syserror("fork");
-
-	if (pid != 0) {
-		/* parent process: tarantool */
-		close(sockpair[1]);
-		master_to_spawner_socket = sockpair[0];
-		sio_setfl(master_to_spawner_socket, O_NONBLOCK, 1);
-	} else {
-		ev_default_fork();
-		ev_loop(EVLOOP_NONBLOCK);
-		/* child process: spawner */
-		close(sockpair[0]);
-		/*
-		 * Move to an own process group, to not receive
-		 * signals from the controlling tty.
-		 */
-		setpgid(0, 0);
-		spawner_init(sockpair[1]);
-	}
-}
-
-/**
- * Create a fiber which accepts client connections and pushes them
- * to replication spawner.
- */
-
-void
-replication_init(const char *bind_ipaddr, int replication_port)
-{
-	if (replication_port == 0)
-		return;                        /* replication is not in use */
-
-	static struct evio_service replication;
-
-	evio_service_init(&replication, "replication", bind_ipaddr,
-			  replication_port, replication_on_accept, NULL);
-
-	evio_service_start(&replication);
-}
-
-
-/*-----------------------------------------------------------------------------*/
-/* replication accept/sender fibers                                            */
-/*-----------------------------------------------------------------------------*/
-
-/** Replication acceptor fiber handler. */
-static void
-replication_on_accept(struct evio_service *service __attribute__((unused)),
-		      int fd,
-		      struct sockaddr_in *addr __attribute__((unused)))
-{
-	/*
-	 * Drop the O_NONBLOCK flag, which was possibly
-	 * inherited from the acceptor fd (happens on
-	 * Darwin).
-         */
-	sio_setfl(fd, O_NONBLOCK, 0);
-
-	struct ev_io *io = (struct ev_io *) malloc(sizeof(struct ev_io));
-	if (io == NULL) {
-		close(fd);
-		return;
-	}
-	io->data = (void *) (intptr_t) fd;
-	ev_io_init(io, replication_send_socket, master_to_spawner_socket, EV_WRITE);
-	ev_io_start(io);
-}
-
-
-/** Send a file descriptor to the spawner. */
-static void
-replication_send_socket(ev_io *watcher, int events __attribute__((unused)))
-{
-	int client_sock = (intptr_t) watcher->data;
-	struct msghdr msg;
-	struct iovec iov[1];
-	char control_buf[CMSG_SPACE(sizeof(int))];
-	struct cmsghdr *control_message = NULL;
-	int cmd_code = 0;
-
-	iov[0].iov_base = &cmd_code;
-	iov[0].iov_len = sizeof(cmd_code);
-
-	memset(&msg, 0, sizeof(msg));
-
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = control_buf;
-	msg.msg_controllen = sizeof(control_buf);
-
-	control_message = CMSG_FIRSTHDR(&msg);
-	control_message->cmsg_len = CMSG_LEN(sizeof(int));
-	control_message->cmsg_level = SOL_SOCKET;
-	control_message->cmsg_type = SCM_RIGHTS;
-	*((int *) CMSG_DATA(control_message)) = client_sock;
-
-	/* Send the client socket to the spawner. */
-	if (sendmsg(master_to_spawner_socket, &msg, 0) < 0)
-		say_syserror("sendmsg");
-
-	ev_io_stop(watcher);
-	free(watcher);
-	/* Close client socket in the main process. */
-	close(client_sock);
-}
-
-
-/*--------------------------------------------------------------------------*
- * spawner process                                                          *
- * -------------------------------------------------------------------------*/
-
-/** Initialize the spawner. */
-
-static void
-spawner_init(int sock)
-{
-	struct sigaction sa;
-
-	title("spawner", NULL);
-	fiber_set_name(fiber_ptr, status);
-
-	/* init replicator process context */
-	spawner.sock = sock;
-
-	/* init signals */
-	memset(&sa, 0, sizeof(sa));
-	sigemptyset(&sa.sa_mask);
-
-	/*
-	 * The spawner normally does not receive any signals,
-	 * except when sent by a system administrator.
-	 * When the master process terminates, it closes its end
-	 * of the socket pair and this signals to the spawner that
-	 * it's time to die as well. But before exiting, the
-	 * spawner must kill and collect all active replication
-	 * relays. This is why we need to change the default
-	 * signal action here.
-	 */
-	sa.sa_handler = spawner_signal_handler;
-
-	if (sigaction(SIGHUP, &sa, NULL) == -1 ||
-	    sigaction(SIGINT, &sa, NULL) == -1 ||
-	    sigaction(SIGTERM, &sa, NULL) == -1)
-		say_syserror("sigaction");
-
-	sa.sa_handler = spawner_sigchld_handler;
-
-	if (sigaction(SIGCHLD, &sa, NULL) == -1)
-		say_syserror("sigaction");
-
-	sa.sa_handler = SIG_IGN;
-	/*
-	 * Ignore SIGUSR1, SIGUSR1 is used to make snapshots,
-	 * and if someone wrote a faulty regexp for `ps' and
-	 * fed it to `kill' the replication shouldn't die.
-	 * Ignore SIGUSR2 as well, since one can be pretty
-	 * inventive in ways of shooting oneself in the foot.
-	 * Ignore SIGPIPE, otherwise we may receive SIGPIPE
-	 * when trying to write to the log.
-	 */
-	if (sigaction(SIGUSR1, &sa, NULL) == -1 ||
-	    sigaction(SIGUSR2, &sa, NULL) == -1 ||
-	    sigaction(SIGPIPE, &sa, NULL) == -1) {
-
-		say_syserror("sigaction");
-	}
-
-	say_crit("initialized");
-	spawner_main_loop();
-}
-
-
-
-static int
-spawner_unpack_cmsg(struct msghdr *msg)
-{
-	struct cmsghdr *control_message;
-	for (control_message = CMSG_FIRSTHDR(msg);
-	     control_message != NULL;
-	     control_message = CMSG_NXTHDR(msg, control_message))
-		if ((control_message->cmsg_level == SOL_SOCKET) &&
-		    (control_message->cmsg_type == SCM_RIGHTS))
-			return *((int *) CMSG_DATA(control_message));
-	assert(false);
-	return -1;
-}
-
-/** Replication spawner process main loop. */
-static void
-spawner_main_loop()
-{
-	struct msghdr msg;
-	struct iovec iov[1];
-	char control_buf[CMSG_SPACE(sizeof(int))];
-	int cmd_code = 0;
-	int client_sock;
-
-	iov[0].iov_base = &cmd_code;
-	iov[0].iov_len = sizeof(cmd_code);
-
-	msg.msg_name = NULL;
-	msg.msg_namelen = 0;
-	msg.msg_iov = iov;
-	msg.msg_iovlen = 1;
-	msg.msg_control = control_buf;
-	msg.msg_controllen = sizeof(control_buf);
-
-	while (!spawner.killed) {
-		int msglen = recvmsg(spawner.sock, &msg, 0);
-		if (msglen > 0) {
-			client_sock = spawner_unpack_cmsg(&msg);
-			spawner_create_replication_relay(client_sock);
-		} else if (msglen == 0) { /* orderly master shutdown */
-			say_info("Exiting: master shutdown");
-			break;
-		} else { /* msglen == -1 */
-			if (errno != EINTR)
-				say_syserror("recvmsg");
-			/* continue, the error may be temporary */
-		}
-	}
-	spawner_shutdown();
-}
-
-/** Replication spawner shutdown. */
-static void
-spawner_shutdown()
-{
-	/*
-	 * There is no need to ever use signals with the spawner
-	 * process. If someone did send spawner a signal by
-	 * mistake, at least make a squeak in the error log before
-	 * dying.
-	 */
-	if (spawner.killed)
-		say_info("Terminated by signal %d", (int) spawner.killed);
-
-	/* close socket */
-	close(spawner.sock);
-
-	/* kill all children */
-	spawner_shutdown_children();
-
-	exit(EXIT_SUCCESS);
-}
-
-/** Replication spawner signal handler for terminating signals. */
-static void spawner_signal_handler(int signal)
-{
-	spawner.killed = signal;
-}
-
-/** Wait for a terminated child. */
-static void
-spawner_sigchld_handler(int signo __attribute__((unused)))
-{
-	static const char waitpid_failed[] = "spawner: waitpid() failed\n";
-	do {
-		int exit_status;
-		pid_t pid = waitpid(-1, &exit_status, WNOHANG);
-		switch (pid) {
-		case -1:
-			if (errno != ECHILD) {
-				int r = write(sayfd, waitpid_failed,
-					      sizeof(waitpid_failed) - 1);
-				(void) r; /* -Wunused-result warning suppression */
-			}
-			return;
-		case 0: /* no more changes in children status */
-			return;
-		default:
-			spawner.child_count--;
-		}
-	} while (spawner.child_count > 0);
-}
-
-/** Create replication client handler process. */
-static int
-spawner_create_replication_relay(int client_sock)
-{
-	pid_t pid = fork();
-
-	if (pid < 0) {
-		say_syserror("fork");
-		return -1;
-	}
-
-	if (pid == 0) {
-		ev_default_fork();
-		ev_loop(EVLOOP_NONBLOCK);
-		close(spawner.sock);
-		replication_relay_loop(client_sock);
-	} else {
-		spawner.child_count++;
-		close(client_sock);
-		say_info("created a replication relay: pid = %d", (int) pid);
-	}
-
-	return 0;
-}
-
-/** Replicator spawner shutdown: kill and wait for children. */
-static void
-spawner_shutdown_children()
-{
-	int kill_signo = SIGTERM, signo;
-	sigset_t mask, orig_mask, alarm_mask;
-
-retry:
-	sigemptyset(&mask);
-	sigaddset(&mask, SIGCHLD);
-	sigaddset(&mask, SIGALRM);
-	/*
-	 * We're going to kill the entire process group, which
-	 * we're part of. Handle the signal sent to ourselves.
-	 */
-	sigaddset(&mask, kill_signo);
-
-	if (spawner.child_count == 0)
-		return;
-
-	/* Block SIGCHLD and SIGALRM to avoid races. */
-	if (sigprocmask(SIG_BLOCK, &mask, &orig_mask)) {
-		say_syserror("sigprocmask");
-		return;
-	}
-
-	/* We'll wait for children no longer than 5 sec.  */
-	alarm(5);
-
-	say_info("sending signal %d to %d children", kill_signo,
-		 (int) spawner.child_count);
-
-	kill(0, kill_signo);
-
-	say_info("waiting for children for up to 5 seconds");
-
-	while (spawner.child_count > 0) {
-		sigwait(&mask, &signo);
-		if (signo == SIGALRM) {         /* timed out */
-			break;
-		}
-		else if (signo != kill_signo) {
-			assert(signo == SIGCHLD);
-			spawner_sigchld_handler(signo);
-		}
-	}
-
-	/* Reset the alarm. */
-	alarm(0);
-
-	/* Clear possibly pending SIGALRM. */
-	sigpending(&alarm_mask);
-	if (sigismember(&alarm_mask, SIGALRM)) {
-		sigemptyset(&alarm_mask);
-		sigaddset(&alarm_mask, SIGALRM);
-		sigwait(&alarm_mask, &signo);
-	}
-
-	/* Restore the old mask. */
-	if (sigprocmask(SIG_SETMASK, &orig_mask, NULL)) {
-		say_syserror("sigprocmask");
-		return;
-	}
-
-	if (kill_signo == SIGTERM) {
-		kill_signo = SIGKILL;
-		goto retry;
-	}
-}
-
-/** A libev callback invoked when a relay client socket is ready
- * for read. This currently only happens when the client closes
- * its socket, and we get an EOF.
- */
-static void
-replication_relay_recv(struct ev_io *w, int __attribute__((unused)) revents)
-{
-	int client_sock = (int) (intptr_t) w->data;
-	uint8_t data;
-
-	int rc = recv(client_sock, &data, sizeof(data), 0);
-
-	if (rc == 0 || (rc < 0 && errno == ECONNRESET)) {
-		say_info("the client has closed its replication socket, exiting");
-		exit(EXIT_SUCCESS);
-	}
-	if (rc < 0)
-		say_syserror("recv");
-
-	exit(EXIT_FAILURE);
-}
-
-
-/** Send a single row to the client. */
-static int
-replication_relay_send_row(void *param, const char *row, uint32_t rowlen)
-{
-	int client_sock = (int) (intptr_t) param;
-	ssize_t bytes, len = rowlen;
-	while (len > 0) {
-		bytes = write(client_sock, row, len);
-		if (bytes < 0) {
-			if (errno == EPIPE) {
-				/* socket closed on opposite site */
-				goto shutdown_handler;
-			}
-			panic_syserror("write");
-		}
-		len -= bytes;
-		row += bytes;
-	}
-
-	return 0;
-shutdown_handler:
-	say_info("the client has closed its replication socket, exiting");
-	exit(EXIT_SUCCESS);
-}
-
-
-/** The main loop of replication client service process. */
-static void
-replication_relay_loop(int client_sock)
-{
-	struct sigaction sa;
-	int64_t lsn;
-	ssize_t r;
-
-	/* Set process title and fiber name.
-	 * Even though we use only the main fiber, the logger
-	 * uses the current fiber name.
-	 */
-	struct sockaddr_in peer;
-	socklen_t addrlen = sizeof(peer);
-	getpeername(client_sock, ((struct sockaddr*)&peer), &addrlen);
-	title("relay", "%s", sio_strfaddr(&peer));
-	fiber_set_name(fiber_ptr, status);
-
-	/* init signals */
-	memset(&sa, 0, sizeof(sa));
-	sigemptyset(&sa.sa_mask);
-
-	/* Reset all signals to their defaults. */
-	sa.sa_handler = SIG_DFL;
-	if (sigaction(SIGCHLD, &sa, NULL) == -1 ||
-	    sigaction(SIGHUP, &sa, NULL) == -1 ||
-	    sigaction(SIGINT, &sa, NULL) == -1 ||
-	    sigaction(SIGTERM, &sa, NULL) == -1)
-		say_syserror("sigaction");
-
-	/*
-	 * Ignore SIGPIPE, we already handle EPIPE.
-	 * Ignore SIGUSR1, SIGUSR1 is used to make snapshots,
-	 * and if someone wrote a faulty regexp for `ps' and
-	 * fed it to `kill' the replication shouldn't die.
-	 * Ignore SIGUSR2 as well, since one can be pretty
-	 * inventive in ways of shooting oneself in the foot.
-	 */
-	sa.sa_handler = SIG_IGN;
-	if (sigaction(SIGPIPE, &sa, NULL) == -1 ||
-	    sigaction(SIGUSR1, &sa, NULL) == -1 ||
-	    sigaction(SIGUSR2, &sa, NULL) == -1) {
-
-		say_syserror("sigaction");
-	}
-
-	r = read(client_sock, &lsn, sizeof(lsn));
-	if (r != sizeof(lsn)) {
-		if (r < 0) {
-			panic_syserror("read");
-		}
-		panic("invalid LSN request size: %zu", r);
-	}
-	say_info("starting replication from lsn: %" PRIi64, lsn);
-
-	replication_relay_send_row((void *)(intptr_t) client_sock,
-				   (const char *) &default_version,
-				   sizeof(default_version));
-
-	/* init libev events handlers */
-	ev_default_loop(0);
-
-	/*
-	 * Init a read event: when replica closes its end
-	 * of the socket, we can read EOF and shutdown the
-	 * relay.
-	 */
-	struct ev_io sock_read_ev;
-	sock_read_ev.data = (void *)(intptr_t) client_sock;
-	ev_io_init(&sock_read_ev, replication_relay_recv, client_sock, EV_READ);
-	ev_io_start(&sock_read_ev);
-
-	/* Initialize the recovery process */
-	recovery_init(cfg.snap_dir, cfg.wal_dir,
-		      replication_relay_send_row, (void *)(intptr_t) client_sock,
-		      INT32_MAX, RECOVER_READONLY);
-	/*
-	 * Note that recovery starts with lsn _NEXT_ to
-	 * the confirmed one.
-	 */
-	recovery_state->lsn = recovery_state->confirmed_lsn = lsn - 1;
-	recover_existing_wals(recovery_state);
-	/* Found nothing. */
-	if (recovery_state->lsn == lsn - 1)
-		say_error("can't find WAL containing record with lsn: %" PRIi64, lsn);
-	recovery_follow_local(recovery_state, 0.1);
-
-	ev_loop(0);
-
-	say_crit("exiting the relay loop");
-	exit(EXIT_SUCCESS);
-}
-
diff --git a/src/session.cc b/src/session.cc
deleted file mode 100644
index 9abdc1acef4faabde7cb1b3fba4deb15154ef15e..0000000000000000000000000000000000000000
--- a/src/session.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "session.h"
-#include "fiber.h"
-
-#include "assoc.h"
-#include "exception.h"
-#include <sys/socket.h>
-
-uint32_t sid_max;
-
-static struct mh_i32ptr_t *session_registry;
-
-struct session_trigger session_on_connect;
-struct session_trigger session_on_disconnect;
-
-uint32_t
-session_create(int fd, uint64_t cookie)
-{
-	/* Return the next sid rolling over the reserved value of 0. */
-	while (++sid_max == 0)
-		;
-
-	uint32_t sid = sid_max;
-	struct mh_i32ptr_node_t node;
-	node.key = sid;
-	node.val = (void *) (intptr_t) fd;
-
-	mh_int_t k = mh_i32ptr_put(session_registry, &node, NULL, NULL);
-
-	if (k == mh_end(session_registry)) {
-		tnt_raise(ClientError, ER_MEMORY_ISSUE,
-			  "session hash", "new session");
-	}
-	/*
-	 * Run the trigger *after* setting the current
-	 * fiber sid.
-	 */
-	fiber_set_sid(fiber_ptr, sid, cookie);
-	if (session_on_connect.trigger) {
-		void *param = session_on_connect.param;
-		try {
-			session_on_connect.trigger(param);
-		} catch (const Exception& e) {
-			fiber_set_sid(fiber_ptr, 0, 0);
-			mh_i32ptr_remove(session_registry, &node, NULL);
-			throw;
-		}
-	}
-
-	return sid;
-}
-
-void
-session_destroy(uint32_t sid)
-{
-	if (sid == 0) /* no-op for a dead session. */
-		return;
-
-	if (session_on_disconnect.trigger) {
-		void *param = session_on_disconnect.param;
-		try {
-			session_on_disconnect.trigger(param);
-		} catch (const Exception& e) {
-			e.log();
-		} catch (...) {
-			/* catch all. */
-		}
-	}
-	session_storage_cleanup(sid);
-	struct mh_i32ptr_node_t node = { sid, NULL };
-	mh_i32ptr_remove(session_registry, &node, NULL);
-}
-
-int
-session_fd(uint32_t sid)
-{
-	struct mh_i32ptr_node_t node = { sid, NULL };
-	mh_int_t k = mh_i32ptr_get(session_registry, &node, NULL);
-	return k == mh_end(session_registry) ?
-		-1 : (intptr_t) mh_i32ptr_node(session_registry, k)->val;
-}
-
-void
-session_init()
-{
-	session_registry = mh_i32ptr_new();
-	if (session_registry == NULL)
-		panic("out of memory");
-}
-
-void
-session_free()
-{
-	if (session_registry)
-		mh_i32ptr_delete(session_registry);
-}
diff --git a/src/tarantool.cc b/src/tarantool.cc
deleted file mode 100644
index ea433395cc447a23a838f00b8a30152abf9d4ac2..0000000000000000000000000000000000000000
--- a/src/tarantool.cc
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- *    copyright notice, this list of conditions and the
- *    following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- *    copyright notice, this list of conditions and the following
- *    disclaimer in the documentation and/or other materials
- *    provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include "tarantool.h"
-#include "tarantool/config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <pwd.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <sysexits.h>
-#if defined(TARGET_OS_LINUX) && defined(HAVE_PRCTL_H)
-# include <sys/prctl.h>
-#endif
-#include <admin.h>
-#include <replication.h>
-#include <fiber.h>
-#include <coeio.h>
-#include <iproto.h>
-#include "mutex.h"
-#include <recovery.h>
-#include <crc32.h>
-#include <palloc.h>
-#include <salloc.h>
-#include <say.h>
-#include <stat.h>
-#include <limits.h>
-#include "tarantool/util.h"
-extern "C" {
-#include <cfg/warning.h>
-#include <cfg/tarantool_box_cfg.h>
-#include <third_party/gopt/gopt.h>
-} /* extern "C" */
-#include "tt_pthread.h"
-#include "lua/init.h"
-#include "memcached.h"
-#include "session.h"
-#include "box/box.h"
-#include "scoped_guard.h"
-
-
-static pid_t master_pid;
-const char *cfg_filename = NULL;
-char *cfg_filename_fullpath = NULL;
-char *binary_filename;
-char *custom_proc_title;
-char status[64] = "unknown";
-char **main_argv;
-int main_argc;
-static void *main_opt = NULL;
-struct tarantool_cfg cfg;
-/** Signals handled after start as part of the event loop. */
-static ev_signal ev_sigs[4];
-static const int ev_sig_count = sizeof(ev_sigs)/sizeof(*ev_sigs);
-
-int snapshot_pid = 0; /* snapshot processes pid */
-uint32_t snapshot_version = 0;
-
-extern const void *opt_def;
-
-/* defined in third_party/proctitle.c */
-extern "C" {
-char **init_set_proc_title(int argc, char **argv);
-void free_proc_title(int argc, char **argv);
-void set_proc_title(const char *format, ...);
-} /* extern "C" */
-
-static int
-core_check_config(struct tarantool_cfg *conf)
-{
-	if (strindex(wal_mode_STRS, conf->wal_mode,
-		     WAL_MODE_MAX) == WAL_MODE_MAX) {
-		out_warning(CNF_OK, "wal_mode %s is not recognized", conf->wal_mode);
-		return -1;
-	}
-	return 0;
-}
-
-void
-title(const char *role, const char *fmt, ...)
-{
-	(void) role;
-
-	va_list ap;
-	char buf[256], *bufptr = buf, *bufend = buf + sizeof(buf);
-	char *statusptr = status, *statusend = status + sizeof(status);
-	statusptr += snprintf(statusptr, statusend - statusptr, "%s", role);
-	bufptr += snprintf(bufptr, bufend - bufptr, "%s%s", role,
-			    custom_proc_title);
-
-	if (fmt != NULL) {
-		const char *s = statusptr;
-		statusptr += snprintf(statusptr, statusend - statusptr, "/");
-		va_start(ap, fmt);
-		statusptr += vsnprintf(statusptr, statusend - statusptr,
-				       fmt, ap);
-		va_end(ap);
-		bufptr += snprintf(bufptr, bufend - bufptr, "%s", s);
-	}
-
-	int ports[] = { cfg.primary_port, cfg.secondary_port,
-			cfg.memcached_port, cfg.admin_port,
-			cfg.replication_port };
-	int *pptr = ports;
-	const char *names[] = { "pri", "sec", "memc", "adm", "rpl", NULL };
-	const char **nptr = names;
-
-	for (; *nptr; nptr++, pptr++)
-		if (*pptr)
-			bufptr += snprintf(bufptr, bufend - bufptr,
-					   " %s: %i", *nptr, *pptr);
-	if (strlen(cfg.bind_ipaddr)) {
-		bufptr += snprintf(bufptr, bufend - bufptr,
-				   ", ip: %s", cfg.bind_ipaddr);
-	}
-
-	set_proc_title(buf);
-}
-
-static int
-load_cfg(struct tarantool_cfg *conf, int32_t check_rdonly)
-{
-	FILE *f;
-	int32_t n_accepted, n_skipped, n_ignored;
-
-	tbuf_reset(cfg_out);
-
-	if (cfg_filename_fullpath != NULL)
-		f = fopen(cfg_filename_fullpath, "r");
-	else
-		f = fopen(cfg_filename, "r");
-
-	if (f == NULL) {
-		out_warning(CNF_OK, "can't open config `%s'", cfg_filename);
-		return -1;
-	}
-
-	int syntax = parse_cfg_file_tarantool_cfg(conf, f, check_rdonly,
-						  &n_accepted,
-						  &n_skipped,
-						  &n_ignored);
-	fclose(f);
-
-	if (syntax != 0)
-		return -1;
-
-	if (check_cfg_tarantool_cfg(conf) != 0)
-		return -1;
-
-	if (n_skipped != 0)
-		return -1;
-
-	if (n_accepted == 0) {
-		out_warning(CNF_OK, "empty configuration file '%s'", cfg_filename);
-		return -1;
-	}
-
-	if (core_check_config(conf) != 0)
-		return -1;
-
-	if (replication_check_config(conf) != 0)
-		return -1;
-
-	return box_check_config(conf);
-}
-
-static int
-core_reload_config(const struct tarantool_cfg *old_conf,
-		   const struct tarantool_cfg *new_conf)
-{
-	if (strcasecmp(old_conf->wal_mode, new_conf->wal_mode) != 0 ||
-	    old_conf->wal_fsync_delay != new_conf->wal_fsync_delay) {
-
-		double new_delay = new_conf->wal_fsync_delay;
-
-		/* Mode has changed: */
-		if (strcasecmp(old_conf->wal_mode, new_conf->wal_mode)) {
-			if (strcasecmp(old_conf->wal_mode, "fsync") == 0 ||
-			    strcasecmp(new_conf->wal_mode, "fsync") == 0) {
-				out_warning(CNF_OK, "wal_mode cannot switch to/from fsync");
-				return -1;
-			}
-		}
-
-		/*
-		 * Unless wal_mode=fsync_delay, wal_fsync_delay is
-		 * irrelevant and must be 0.
-		 */
-		if (strcasecmp(new_conf->wal_mode, "fsync_delay") != 0)
-			new_delay = 0.0;
-
-
-		recovery_update_mode(recovery_state, new_conf->wal_mode, new_delay);
-	}
-
-	if (old_conf->snap_io_rate_limit != new_conf->snap_io_rate_limit)
-		recovery_update_io_rate_limit(recovery_state, new_conf->snap_io_rate_limit);
-
-	if (old_conf->io_collect_interval != new_conf->io_collect_interval)
-		ev_set_io_collect_interval(new_conf->io_collect_interval);
-
-	return 0;
-}
-
-int
-reload_cfg(struct tbuf *out)
-{
-	static struct mutex *mutex = NULL;
-	struct tarantool_cfg new_cfg, aux_cfg;
-
-	if (mutex == NULL) {
-		mutex = (struct mutex *) palloc(eter_pool, sizeof(*mutex));
-		mutex_create(mutex);
-	}
-
-	if (mutex_trylock(mutex) == true) {
-		out_warning(CNF_OK, "Could not reload configuration: it is being reloaded right now");
-		tbuf_append(out, cfg_out->data, cfg_out->size);
-
-		return -1;
-	}
-
-
-	auto scoped_guard = make_scoped_guard([&] {
-		destroy_tarantool_cfg(&aux_cfg);
-		destroy_tarantool_cfg(&new_cfg);
-
-		if (cfg_out->size != 0)
-			tbuf_append(out, cfg_out->data, cfg_out->size);
-
-		mutex_unlock(mutex);
-	});
-
-	init_tarantool_cfg(&new_cfg);
-	init_tarantool_cfg(&aux_cfg);
-
-	/*
-	  Prepare a copy of the original config file
-	   for confetti, so that it can compare the new
-	  file with the old one when loading the new file.
-	  Load the new file and return an error if it
-	  contains a different value for some read-only
-	  parameter.
-	*/
-	if (dup_tarantool_cfg(&aux_cfg, &cfg) != 0 ||
-	    load_cfg(&aux_cfg, 1) != 0)
-		return -1;
-	/*
-	  Load the new configuration file, but
-	  skip the check for read only parameters.
-	  new_cfg contains only defaults and
-	  new settings.
-	*/
-	if (fill_default_tarantool_cfg(&new_cfg) != 0 ||
-	    load_cfg(&new_cfg, 0) != 0)
-		return -1;
-
-	/* Check that no default value has been changed. */
-	char *diff = cmp_tarantool_cfg(&aux_cfg, &new_cfg, 1);
-	if (diff != NULL) {
-		out_warning(CNF_OK, "Could not accept read only '%s' option", diff);
-		return -1;
-	}
-
-	/* Process wal-writer-related changes. */
-	if (core_reload_config(&cfg, &new_cfg) != 0)
-		return -1;
-
-	/* Now pass the config to the module, to take action. */
-	if (box_reload_config(&cfg, &new_cfg) != 0)
-		return -1;
-	/* All OK, activate the config. */
-	swap_tarantool_cfg(&cfg, &new_cfg);
-	tarantool_lua_load_cfg(tarantool_L, &cfg);
-
-	return 0;
-}
-
-/** Print the configuration file in YAML format. */
-void
-show_cfg(struct tbuf *out)
-{
-	tarantool_cfg_iterator_t *i;
-	char *key, *value;
-
-	tbuf_printf(out, "configuration:" CRLF);
-	i = tarantool_cfg_iterator_init();
-	while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
-		if (value) {
-			tbuf_printf(out, "  %s: \"%s\"" CRLF, key, value);
-			free(value);
-		} else {
-			tbuf_printf(out, "  %s: (null)" CRLF, key);
-		}
-	}
-}
-
-const char *
-tarantool_version(void)
-{
-	return PACKAGE_VERSION;
-}
-
-static double start_time;
-
-double
-tarantool_uptime(void)
-{
-	return ev_now() - start_time;
-}
-
-int
-snapshot(void)
-{
-	if (snapshot_pid)
-		return EINPROGRESS;
-
-
-	pid_t p = fork();
-	if (p < 0) {
-		say_syserror("fork");
-		return -1;
-	}
-	if (p > 0) {
-		snapshot_pid = p;
-		/* increment snapshot version */
-		snapshot_version++;
-		int status = wait_for_child(p);
-		snapshot_pid = 0;
-		return (WIFSIGNALED(status) ? EINTR : WEXITSTATUS(status));
-	}
-
-	salloc_protect();
-
-	title("dumper", "%" PRIu32, getppid());
-	fiber_set_name(fiber_ptr, status);
-
-	/*
-	 * Safety: make sure we don't double-write
-	 * parent stdio buffers at exit().
-	 */
-	close_all_xcpt(1, sayfd);
-	/*
-	 * We must avoid double destruction of tuples on exit.
-	 * Since there is no way to remove existing handlers
-	 * registered in the master process, and snapshot_save()
-	 * may call exit(), push a top-level handler which will do
-	 * _exit() for us.
-	 */
-	snapshot_save(recovery_state, box_snapshot);
-
-	exit(EXIT_SUCCESS);
-	return 0;
-}
-
-
-/**
-* Create snapshot from signal handler (SIGUSR1)
-*/
-static void
-sig_snapshot(struct ev_signal *w, int revents)
-{
-	(void) w;
-	(void) revents;
-
-	if (snapshot_pid) {
-		say_warn("Snapshot process is already running,"
-			" the signal is ignored");
-		return;
-	}
-	fiber_call(fiber_new("snapshot", (fiber_func)snapshot));
-}
-
-static void
-signal_cb(struct ev_signal *w, int revents)
-{
-	(void) w;
-	(void) revents;
-
-	/* Terminate the main event loop */
-	ev_unloop(EV_A_ EVUNLOOP_ALL);
-}
-
-/** Try to log as much as possible before dumping a core.
- *
- * Core files are not aways allowed and it takes an effort to
- * extract useful information from them.
- *
- * *Recursive invocation*
- *
- * Unless SIGSEGV is sent by kill(), Linux
- * resets the signal a default value before invoking
- * the handler.
- *
- * Despite that, as an extra precaution to avoid infinite
- * recursion, we count invocations of the handler, and
- * quietly _exit() when called for a second time.
- */
-static void
-sig_fatal_cb(int signo)
-{
-	static volatile sig_atomic_t in_cb = 0;
-	int fd = STDERR_FILENO;
-	struct sigaction sa;
-
-	/* Got a signal while running the handler. */
-	if (in_cb) {
-		fdprintf(fd, "Fatal %d while backtracing", signo);
-		goto end;
-	}
-
-	in_cb = 1;
-
-	if (signo == SIGSEGV)
-		fdprintf(fd, "Segmentation fault\n");
-	else
-		fdprintf(fd, "Got a fatal signal %d\n", signo);
-
-	fdprintf(fd, "Current time: %u\n", (unsigned) time(0));
-	fdprintf(fd,
-		 "Please file a bug at http://github.com/tarantool/tarantool/issues\n"
-		 "Attempting backtrace... Note: since the server has "
-		 "already crashed, \nthis may fail as well\n");
-#ifdef ENABLE_BACKTRACE
-	print_backtrace();
-#endif
-end:
-	/* Try to dump core. */
-	memset(&sa, 0, sizeof(sa));
-	sigemptyset(&sa.sa_mask);
-	sa.sa_handler = SIG_DFL;
-	sigaction(SIGABRT, &sa, NULL);
-
-	abort();
-}
-
-/**
- * This SIGTERM handler is only used before the main event loop started to
- * cleanup server pid file. The handler is replaced by ev_signal after the boot.
- * @sa signal_start
- */
-static void
-sig_term_cb(int signo)
-{
-	psignal(signo, "");
-	/* unlink pidfile. */
-	if (cfg.pid_file != NULL)
-		unlink(cfg.pid_file);
-
-	_exit(EXIT_SUCCESS);
-}
-
-static void
-signal_free(void)
-{
-	int i;
-	for (i = 0; i < ev_sig_count; i++)
-		ev_signal_stop(&ev_sigs[i]);
-}
-
-static void
-signal_start(void)
-{
-	for (int i = 0; i < ev_sig_count; i++)
-		ev_signal_start(&ev_sigs[i]);
-}
-
-/** Make sure the child has a default signal disposition. */
-static void
-signal_reset()
-{
-	struct sigaction sa;
-
-	/* Reset all signals to their defaults. */
-	memset(&sa, 0, sizeof(sa));
-	sigemptyset(&sa.sa_mask);
-	sa.sa_handler = SIG_DFL;
-
-	if (sigaction(SIGUSR1, &sa, NULL) == -1 ||
-	    sigaction(SIGINT, &sa, NULL) == -1 ||
-	    sigaction(SIGTERM, &sa, NULL) == -1 ||
-	    sigaction(SIGHUP, &sa, NULL) == -1 ||
-	    sigaction(SIGSEGV, &sa, NULL) == -1 ||
-	    sigaction(SIGFPE, &sa, NULL) == -1)
-		say_syserror("sigaction");
-
-	/* Unblock any signals blocked by libev. */
-	sigset_t sigset;
-	sigfillset(&sigset);
-	if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1)
-		say_syserror("sigprocmask");
-}
-
-
-/**
- * Adjust the process signal mask and add handlers for signals.
- */
-static void
-signal_init(void)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-
-	sa.sa_handler = SIG_IGN;
-	sigemptyset(&sa.sa_mask);
-
-	if (sigaction(SIGPIPE, &sa, 0) == -1)
-		panic_syserror("sigaction");
-
-	sa.sa_handler = sig_fatal_cb;
-
-	if (sigaction(SIGSEGV, &sa, 0) == -1 ||
-	    sigaction(SIGFPE, &sa, 0) == -1) {
-		panic_syserror("sigaction");
-	}
-
-	sa.sa_handler = sig_term_cb;
-	if (sigaction(SIGUSR1, &sa, 0) == -1 ||
-	    sigaction(SIGINT, &sa, 0) == -1  ||
-	    sigaction(SIGTERM, &sa, 0) == -1 ||
-	    sigaction(SIGHUP, &sa, 0) == -1) {
-		panic_syserror("sigaction");
-	}
-
-	ev_signal_init(&ev_sigs[0], sig_snapshot, SIGUSR1);
-	ev_signal_init(&ev_sigs[1], signal_cb, SIGINT);
-	ev_signal_init(&ev_sigs[2], signal_cb, SIGTERM);
-	ev_signal_init(&ev_sigs[3], signal_cb, SIGHUP);
-
-	(void) tt_pthread_atfork(NULL, NULL, signal_reset);
-}
-
-static void
-create_pid(void)
-{
-	FILE *f;
-	char buf[16] = { 0 };
-	pid_t pid;
-
-	if (cfg.pid_file == NULL)
-		return;
-
-	f = fopen(cfg.pid_file, "a+");
-	if (f == NULL)
-		panic_syserror("can't open pid file");
-	/*
-	 * fopen() is not guaranteed to set the seek position to
-	 * the beginning of file according to ANSI C (and, e.g.,
-	 * on FreeBSD.
-	 */
-	if (fseeko(f, 0, SEEK_SET) != 0)
-		panic_syserror("can't fseek to the beginning of pid file");
-
-	if (fgets(buf, sizeof(buf), f) != NULL && strlen(buf) > 0) {
-		pid = strtol(buf, NULL, 10);
-		if (pid > 0 && kill(pid, 0) == 0)
-			panic("the daemon is already running");
-		else
-			say_info("updating a stale pid file");
-		if (fseeko(f, 0, SEEK_SET) != 0)
-			panic_syserror("can't fseek to the beginning of pid file");
-		if (ftruncate(fileno(f), 0) == -1)
-			panic_syserror("ftruncate(`%s')", cfg.pid_file);
-	}
-
-	master_pid = getpid();
-	fprintf(f, "%i\n", master_pid);
-	fclose(f);
-}
-
-/** Run in the background. */
-static void
-background()
-{
-	switch (fork()) {
-	case -1:
-		goto error;
-	case 0:                                     /* child */
-		break;
-	default:                                    /* parent */
-		exit(EXIT_SUCCESS);
-	}
-
-	if (setsid() == -1)
-		goto error;
-
-	/*
-	 * Prints to stdout on failure, so got to be done before
-	 * we close it.
-	 */
-	create_pid();
-
-	close(STDIN_FILENO);
-	close(STDOUT_FILENO);
-	close(STDERR_FILENO);
-	return;
-error:
-	exit(EXIT_FAILURE);
-}
-
-void
-tarantool_lua_free()
-{
-	/*
-	 * Got to be done prior to anything else, since GC
-	 * handlers can refer to other subsystems (e.g. fibers).
-	 */
-	if (tarantool_L)
-		tarantool_lua_close(tarantool_L);
-	tarantool_L = NULL;
-}
-
-void
-tarantool_free(void)
-{
-	/* Do nothing in a fork. */
-	if (getpid() != master_pid)
-		return;
-	signal_free();
-	memcached_free();
-	tarantool_lua_free();
-	box_free();
-	recovery_free();
-	stat_free();
-
-	if (cfg_filename_fullpath)
-		free(cfg_filename_fullpath);
-	if (main_opt)
-		gopt_free(main_opt);
-	free_proc_title(main_argc, main_argv);
-
-	/* unlink pidfile. */
-	if (cfg.pid_file != NULL)
-		unlink(cfg.pid_file);
-	destroy_tarantool_cfg(&cfg);
-
-	session_free();
-	fiber_free();
-	palloc_free();
-	ev_default_destroy();
-#ifdef ENABLE_GCOV
-	__gcov_flush();
-#endif
-#ifdef HAVE_BFD
-	symbols_free();
-#endif
-	/* A hack for cc/ld, see ffisyms.c */
-	if (time(NULL) == 0) {
-		/* never executed */
-		extern void *ffi_symbols[];
-		write(0, ffi_symbols, 0);
-	}
-}
-
-static void
-initialize_minimal()
-{
-	if (!salloc_init(64 * 1000 * 1000, 4, 2))
-		panic("can't initialize slab allocator");
-
-	fiber_init();
-	coeio_init();
-}
-
-int
-main(int argc, char **argv)
-{
-	const char *cfg_paramname = NULL;
-
-#ifndef HAVE_LIBC_STACK_END
-/*
- * GNU libc provides a way to get at the top of the stack. This
- * is, of course, not-standard and doesn't work on non-GNU
- * systems, such as FreeBSD. But as far as we're concerned, argv
- * is at the top of the main thread's stack, so save the address
- * of it.
- */
-	__libc_stack_end = (void*) &argv;
-#endif
-
-	crc32_init();
-	stat_init();
-	palloc_init();
-
-#ifdef HAVE_BFD
-	symbols_load(argv[0]);
-#endif
-
-	argv = init_set_proc_title(argc, argv);
-	main_argc = argc;
-	main_argv = argv;
-
-	void *opt = gopt_sort(&argc, (const char **)argv, opt_def);
-	main_opt = opt;
-	binary_filename = argv[0];
-
-	if (gopt(opt, 'V')) {
-		printf("Tarantool %s\n", tarantool_version());
-		printf("Target: %s\n", BUILD_INFO);
-		printf("Build options: %s\n", BUILD_OPTIONS);
-		printf("Compiler: %s\n", COMPILER_INFO);
-		printf("C_FLAGS:%s\n", TARANTOOL_C_FLAGS);
-		printf("CXX_FLAGS:%s\n", TARANTOOL_CXX_FLAGS);
-		return 0;
-	}
-
-	if (gopt(opt, 'h')) {
-		puts("Tarantool -- an efficient in-memory data store.");
-		printf("Usage: %s [OPTIONS]\n", basename(argv[0]));
-		puts("");
-		gopt_help(opt_def);
-		puts("");
-		puts("Please visit project home page at http://tarantool.org");
-		puts("to see online documentation, submit bugs or contribute a patch.");
-		return 0;
-	}
-
-	gopt_arg(opt, 'c', &cfg_filename);
-	/*
-	 * if config is not specified trying ./tarantool.cfg then
-	 * /etc/tarantool.cfg
-	 */
-	if (cfg_filename == NULL) {
-		if (access(DEFAULT_CFG_FILENAME, F_OK) == 0)
-			cfg_filename = DEFAULT_CFG_FILENAME;
-		else if (access(DEFAULT_CFG, F_OK) == 0)
-			cfg_filename = DEFAULT_CFG;
-		else
-			panic("can't load config " "%s or %s", DEFAULT_CFG_FILENAME, DEFAULT_CFG);
-	}
-
-	cfg.log_level += gopt(opt, 'v');
-
-	if (argc != 1) {
-		fprintf(stderr, "Can't parse command line: try --help or -h for help.\n");
-		exit(EX_USAGE);
-	}
-
-	if (cfg_filename[0] != '/') {
-		cfg_filename_fullpath = (char *) malloc(PATH_MAX);
-		if (getcwd(cfg_filename_fullpath, PATH_MAX - strlen(cfg_filename) - 1) == NULL) {
-			say_syserror("getcwd");
-			exit(EX_OSERR);
-		}
-
-		strcat(cfg_filename_fullpath, "/");
-		strcat(cfg_filename_fullpath, cfg_filename);
-	}
-
-	cfg_out = tbuf_new(eter_pool);
-	assert(cfg_out);
-
-	if (gopt(opt, 'k')) {
-		if (fill_default_tarantool_cfg(&cfg) != 0 || load_cfg(&cfg, 0) != 0) {
-			say_error("check_config FAILED"
-				  "%.*s", cfg_out->size, (char *)cfg_out->data);
-
-			return 1;
-		}
-
-		return 0;
-	}
-
-	if (fill_default_tarantool_cfg(&cfg) != 0 || load_cfg(&cfg, 0) != 0)
-		panic("can't load config:"
-		      "%.*s", cfg_out->size, (char *)cfg_out->data);
-
-	if (gopt_arg(opt, 'g', &cfg_paramname)) {
-		tarantool_cfg_iterator_t *i;
-		char *key, *value;
-
-		i = tarantool_cfg_iterator_init();
-		while ((key = tarantool_cfg_iterator_next(i, &cfg, &value)) != NULL) {
-			if (strcmp(key, cfg_paramname) == 0 && value != NULL) {
-				printf("%s\n", value);
-				free(value);
-
-				return 0;
-			}
-
-			free(value);
-		}
-
-		return 1;
-	}
-
-	if (cfg.work_dir != NULL && chdir(cfg.work_dir) == -1)
-		say_syserror("can't chdir to `%s'", cfg.work_dir);
-
-	if (cfg.username != NULL) {
-		if (getuid() == 0 || geteuid() == 0) {
-			struct passwd *pw;
-			errno = 0;
-			if ((pw = getpwnam(cfg.username)) == 0) {
-				if (errno) {
-					say_syserror("getpwnam: %s",
-						     cfg.username);
-				} else {
-					say_error("User not found: %s",
-						  cfg.username);
-				}
-				exit(EX_NOUSER);
-			}
-			if (setgid(pw->pw_gid) < 0 || setuid(pw->pw_uid) < 0 || seteuid(pw->pw_uid)) {
-				say_syserror("setgit/setuid");
-				exit(EX_OSERR);
-			}
-		} else {
-			say_error("can't switch to %s: i'm not root", cfg.username);
-		}
-	}
-
-	if (cfg.coredump) {
-		struct rlimit c = { 0, 0 };
-		if (getrlimit(RLIMIT_CORE, &c) < 0) {
-			say_syserror("getrlimit");
-			exit(EX_OSERR);
-		}
-		c.rlim_cur = c.rlim_max;
-		if (setrlimit(RLIMIT_CORE, &c) < 0) {
-			say_syserror("setrlimit");
-			exit(EX_OSERR);
-		}
-#if defined(TARGET_OS_LINUX) && defined(HAVE_PRCTL_H)
-		if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
-			say_syserror("prctl");
-			exit(EX_OSERR);
-		}
-#endif
-	}
-
-	if (gopt(opt, 'I')) {
-		initialize_minimal();
-		box_init(true);
-		set_lsn(recovery_state, 1);
-		snapshot_save(recovery_state, NULL);
-		exit(EXIT_SUCCESS);
-	}
-
-	if (gopt(opt, 'B')) {
-		if (cfg.logger == NULL) {
-			say_crit("--background requires 'logger' configuration option to be set");
-			exit(EXIT_FAILURE);
-		}
-		background();
-	}
-	else {
-		create_pid();
-	}
-
-	/* init process title - used for logging */
-	if (cfg.custom_proc_title == NULL) {
-		custom_proc_title = (char *) palloc(eter_pool, 1);
-		custom_proc_title[0] = '\0';
-	} else {
-		custom_proc_title = (char *) palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
-		strcpy(custom_proc_title, "@");
-		strcat(custom_proc_title, cfg.custom_proc_title);
-	}
-
-	say_logger_init(cfg.logger_nonblock);
-
-	/* main core cleanup routine */
-	atexit(tarantool_free);
-
-	ev_default_loop(EVFLAG_AUTO);
-	fiber_init();
-	replication_prefork();
-	coeio_init();
-	if (!salloc_init(cfg.slab_alloc_arena * (1 << 30) /* GB */,
-		    cfg.slab_alloc_minimal, cfg.slab_alloc_factor))
-		panic("can't initialize slab allocator");
-
-	signal_init();
-
-	try {
-		say_crit("version %s", tarantool_version());
-		tarantool_L = tarantool_lua_init();
-		box_init(false);
-		memcached_init(cfg.bind_ipaddr, cfg.memcached_port);
-		tarantool_lua_load_cfg(tarantool_L, &cfg);
-		/*
-		 * init iproto before admin and after memcached:
-		 * recovery is finished on bind to the primary port,
-		 * and it has to happen before requests on the
-		 * administrative port start to arrive.
-		 * And when recovery is finalized, memcached
-		 * expire loop is started, so binding can happen
-		 * only after memcached is initialized.
-		 */
-		iproto_init(cfg.bind_ipaddr, cfg.primary_port,
-			    cfg.secondary_port);
-		admin_init(cfg.bind_ipaddr, cfg.admin_port);
-		replication_init(cfg.bind_ipaddr, cfg.replication_port);
-		session_init();
-		/*
-		 * Load user init script.  The script should have access
-		 * to Tarantool Lua API (box.cfg, box.fiber, etc...) that
-		 * is why script must run only after the server was fully
-		 * initialized.
-		 */
-		tarantool_lua_load_init_script(tarantool_L);
-		prelease(fiber_ptr->gc_pool);
-		say_crit("log level %i", cfg.log_level);
-		say_crit("entering event loop");
-		if (cfg.io_collect_interval > 0)
-			ev_set_io_collect_interval(cfg.io_collect_interval);
-		ev_now_update();
-		start_time = ev_now();
-		signal_start();
-		ev_loop(0);
-	} catch (const Exception& e) {
-		e.log();
-		panic("%s", "Fatal error, exiting loop");
-	}
-
-	say_crit("exiting loop");
-	/* freeing resources */
-	return 0;
-}