From: Vladimir Davydov via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: tarantool-patches@dev.tarantool.org
Subject: [Tarantool-patches] [PATCH 17/20] net.box: rewrite console handlers in C
Date: Fri, 23 Jul 2021 14:07:27 +0300 [thread overview]
Message-ID: <c48b13b50aea34d6199abfaa40970ab7fd1a3236.1627024646.git.vdavydov@tarantool.org> (raw)
In-Reply-To: <cover.1627024646.git.vdavydov@tarantool.org>
Strictly speaking, it's not necessary, because console performance is
not a problem. We do this for consistency with iproto.
---
src/box/lua/net_box.c | 135 ++++++++++++++++++++++++++--------------
src/box/lua/net_box.lua | 49 +++++----------
2 files changed, 106 insertions(+), 78 deletions(-)
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index 1a615797d485..85a45c54b979 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -850,30 +850,25 @@ netbox_send_and_recv_iproto(lua_State *L)
/*
* Sends and receives data over a console connection.
- * Takes socket fd, send_buf (ibuf), recv_buf (ibuf), timeout.
- * On success returns response (string).
- * On error returns nil, error.
+ * Returns a pointer to a response string and its len.
+ * On error returns NULL.
*/
-static int
-netbox_send_and_recv_console(lua_State *L)
+static const char *
+netbox_send_and_recv_console(int fd, struct ibuf *send_buf,
+ struct ibuf *recv_buf, double timeout,
+ size_t *response_len)
{
- int fd = lua_tointeger(L, 1);
- struct ibuf *send_buf = (struct ibuf *) lua_topointer(L, 2);
- struct ibuf *recv_buf = (struct ibuf *) lua_topointer(L, 3);
- double timeout = (!lua_isnoneornil(L, 4) ?
- lua_tonumber(L, 4) : TIMEOUT_INFINITY);
const char delim[] = "\n...\n";
size_t delim_len = sizeof(delim) - 1;
size_t delim_pos;
if (netbox_communicate(fd, send_buf, recv_buf, /*limit=*/SIZE_MAX,
delim, delim_len, timeout, &delim_pos) != 0) {
-
- luaL_testcancel(L);
- return luaT_push_nil_and_error(L);
+ return NULL;
}
- lua_pushlstring(L, recv_buf->rpos, delim_pos + delim_len);
+ const char *response = recv_buf->rpos;
recv_buf->rpos += delim_pos + delim_len;
- return 1;
+ *response_len = delim_pos + delim_len;
+ return response;
}
static void
@@ -1456,23 +1451,6 @@ luaT_netbox_registry_new_id(struct lua_State *L)
return 1;
}
-/*
- * Returns the next id (sync) without reserving it.
- * If called with an argument, returns the id following its value.
- */
-static int
-luaT_netbox_registry_next_id(struct lua_State *L)
-{
- struct netbox_registry *registry = luaT_check_netbox_registry(L, 1);
- uint64_t next_sync;
- if (lua_isnoneornil(L, 2))
- next_sync = registry->next_sync;
- else
- next_sync = luaL_touint64(L, 2) + 1;
- luaL_pushuint64(L, next_sync);
- return 1;
-}
-
static int
luaT_netbox_registry_reset(struct lua_State *L)
{
@@ -1802,24 +1780,93 @@ netbox_dispatch_response_iproto(struct lua_State *L)
/*
* Given a request registry, request id (sync), and a response string, assigns
* the response to the request and completes it.
+ *
+ * Lua stack is used for temporarily storing the response string before getting
+ * a reference to it.
*/
-static int
-netbox_dispatch_response_console(struct lua_State *L)
+static void
+netbox_dispatch_response_console(struct lua_State *L,
+ struct netbox_registry *registry,
+ uint64_t sync, const char *response,
+ size_t response_len)
{
- struct netbox_registry *registry = luaT_check_netbox_registry(L, 1);
- uint64_t sync = luaL_touint64(L, 2);
struct netbox_request *request = netbox_registry_lookup(registry, sync);
if (request == NULL) {
/* Nobody is waiting for the response. */
- return 0;
+ return;
}
- /*
- * The response is the last argument of this function so it's already
- * on the top of the Lua stack.
- */
+ lua_pushlstring(L, response, response_len);
netbox_request_set_result(request, luaL_ref(L, LUA_REGISTRYINDEX));
netbox_request_complete(request);
+}
+
+/*
+ * Sets up console delimiter. Should be called before serving any requests.
+ * Takes socket fd, send_buf (ibuf), recv_buf (ibuf), timeout.
+ * Returns none on success, error on failure.
+ */
+static int
+netbox_console_setup(struct lua_State *L)
+{
+ static const char setup_delimiter_cmd[] =
+ "require('console').delimiter('$EOF$')\n";
+ static const size_t setup_delimiter_cmd_len =
+ sizeof(setup_delimiter_cmd) - 1;
+ static const char ok_response[] = "---\n...\n";
+ static const size_t ok_response_len = sizeof(ok_response) - 1;
+ int fd = lua_tointeger(L, 1);
+ struct ibuf *send_buf = (struct ibuf *) lua_topointer(L, 2);
+ struct ibuf *recv_buf = (struct ibuf *) lua_topointer(L, 3);
+ double timeout = (!lua_isnoneornil(L, 4) ?
+ lua_tonumber(L, 4) : TIMEOUT_INFINITY);
+ void *wpos = ibuf_alloc(send_buf, setup_delimiter_cmd_len);
+ if (wpos == NULL)
+ return luaL_error(L, "out of memory");
+ memcpy(wpos, setup_delimiter_cmd, setup_delimiter_cmd_len);
+ size_t response_len;
+ const char *response = netbox_send_and_recv_console(
+ fd, send_buf, recv_buf, timeout, &response_len);
+ if (response == NULL) {
+ luaL_testcancel(L);
+ goto error;
+ }
+ if (strncmp(response, ok_response, ok_response_len) != 0) {
+ box_error_raise(ER_NO_CONNECTION, "Unexpected response");
+ goto error;
+ }
return 0;
+error:
+ luaT_pusherror(L, box_error_last());
+ return 1;
+}
+
+/*
+ * Processes console requests in a loop until an error.
+ * Takes request registry, socket fd, send_buf (ibuf), recv_buf (ibuf), timeout.
+ * Returns the error that broke the loop.
+ */
+static int
+netbox_console_loop(struct lua_State *L)
+{
+ struct netbox_registry *registry = luaT_check_netbox_registry(L, 1);
+ int fd = lua_tointeger(L, 2);
+ struct ibuf *send_buf = (struct ibuf *) lua_topointer(L, 3);
+ struct ibuf *recv_buf = (struct ibuf *) lua_topointer(L, 4);
+ double timeout = (!lua_isnoneornil(L, 5) ?
+ lua_tonumber(L, 5) : TIMEOUT_INFINITY);
+ uint64_t sync = registry->next_sync;
+ while (true) {
+ size_t response_len;
+ const char *response = netbox_send_and_recv_console(
+ fd, send_buf, recv_buf, timeout, &response_len);
+ if (response == NULL) {
+ luaL_testcancel(L);
+ luaT_pusherror(L, box_error_last());
+ return 1;
+ }
+ netbox_dispatch_response_console(L, registry, sync++,
+ response, response_len);
+ }
}
int
@@ -1828,7 +1875,6 @@ luaopen_net_box(struct lua_State *L)
static const struct luaL_Reg netbox_registry_meta[] = {
{ "__gc", luaT_netbox_registry_gc },
{ "new_id", luaT_netbox_registry_new_id },
- { "next_id", luaT_netbox_registry_next_id },
{ "reset", luaT_netbox_registry_reset },
{ NULL, NULL }
};
@@ -1850,12 +1896,11 @@ luaopen_net_box(struct lua_State *L)
{ "encode_method", netbox_encode_method },
{ "decode_greeting",netbox_decode_greeting },
{ "send_and_recv_iproto", netbox_send_and_recv_iproto },
- { "send_and_recv_console", netbox_send_and_recv_console },
{ "new_registry", netbox_new_registry },
{ "new_request", netbox_new_request },
{ "dispatch_response_iproto", netbox_dispatch_response_iproto },
- { "dispatch_response_console",
- netbox_dispatch_response_console },
+ { "console_setup", netbox_console_setup },
+ { "console_loop", netbox_console_loop },
{ NULL, NULL}
};
/* luaL_register_module polutes _G */
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 0643477cbc9c..0a21c1341117 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -327,10 +327,6 @@ local function create_transport(host, port, user, password, callback,
body_rpos, body_end)
end
- local function dispatch_response_console(rid, response)
- internal.dispatch_response_console(requests, rid, response)
- end
-
-- IO (WORKER FIBER) --
local function send_and_recv_iproto(timeout)
local hdr, body_rpos, body_end = internal.send_and_recv_iproto(
@@ -342,22 +338,14 @@ local function create_transport(host, port, user, password, callback,
return nil, hdr, body_rpos, body_end
end
- local function send_and_recv_console(timeout)
- local response, err = internal.send_and_recv_console(
- connection:fd(), send_buf, recv_buf, timeout)
- if not response then
- return err.code, err.message
- end
- return nil, response
- end
-
-- PROTOCOL STATE MACHINE (WORKER FIBER) --
--
-- The sm is implemented as a collection of functions performing
-- tail-recursive calls to each other. Yep, Lua optimizes
-- such calls, and yep, this is the canonical way to implement
-- a state machine in Lua.
- local console_sm, iproto_auth_sm, iproto_schema_sm, iproto_sm, error_sm
+ local console_setup_sm, console_sm, iproto_auth_sm, iproto_schema_sm,
+ iproto_sm, error_sm
--
-- Protocol_sm is a core function of netbox. It calls all
@@ -376,19 +364,7 @@ local function create_transport(host, port, user, password, callback,
end
-- @deprecated since 1.10
if greeting.protocol == 'Lua console' then
- log.warn("Netbox text protocol support is deprecated since 1.10, "..
- "please use require('console').connect() instead")
- local setup_delimiter = 'require("console").delimiter("$EOF$")\n'
- encode_method(M_INJECT, send_buf, nil, setup_delimiter)
- local err, response = send_and_recv_console()
- if err then
- return error_sm(err, response)
- elseif response ~= '---\n...\n' then
- return error_sm(E_NO_CONNECTION, 'Unexpected response')
- end
- local rid = requests:next_id()
- set_state('active')
- return console_sm(rid)
+ return console_setup_sm()
elseif greeting.protocol == 'Binary' then
return iproto_auth_sm(greeting.salt)
else
@@ -397,14 +373,21 @@ local function create_transport(host, port, user, password, callback,
end
end
- console_sm = function(rid)
- local err, response = send_and_recv_console()
+ console_setup_sm = function()
+ log.warn("Netbox text protocol support is deprecated since 1.10, "..
+ "please use require('console').connect() instead")
+ local err = internal.console_setup(connection:fd(), send_buf, recv_buf)
if err then
- return error_sm(err, response)
- else
- dispatch_response_console(rid, response)
- return console_sm(requests:next_id(rid))
+ return error_sm(err.code, err.message)
end
+ set_state('active')
+ return console_sm()
+ end
+
+ console_sm = function()
+ local err = internal.console_loop(requests, connection:fd(),
+ send_buf, recv_buf)
+ return error_sm(err.code, err.message)
end
iproto_auth_sm = function(salt)
--
2.25.1
next prev parent reply other threads:[~2021-07-23 11:16 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-23 11:07 [Tarantool-patches] [PATCH 00/20] Rewrite performance critical parts of net.box " Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 01/20] net.box: fix console connection breakage when request is discarded Vladimir Davydov via Tarantool-patches
2021-07-28 22:49 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-29 10:40 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 02/20] net.box: wake up wait_result callers " Vladimir Davydov via Tarantool-patches
2021-07-29 10:47 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 03/20] net.box: do not check worker_fiber in request:result, is_ready Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 04/20] net.box: remove decode_push from method_decoder table Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 05/20] net.box: use decode_tuple instead of decode_get Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 06/20] net.box: rename request.ctx to request.format Vladimir Davydov via Tarantool-patches
2021-07-28 22:49 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-29 10:54 ` Vladimir Davydov via Tarantool-patches
2021-07-29 22:39 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-30 8:15 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 07/20] net.box: use integer id instead of method name Vladimir Davydov via Tarantool-patches
2021-07-28 22:50 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-29 11:30 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 08/20] net.box: remove useless encode optimization Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 09/20] net.box: rewrite request encoder in C Vladimir Davydov via Tarantool-patches
2021-07-28 22:51 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-29 14:08 ` Vladimir Davydov via Tarantool-patches
2021-07-29 14:10 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 10/20] lua/utils: make char ptr Lua CTIDs public Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 11/20] net.box: rewrite response decoder in C Vladimir Davydov via Tarantool-patches
2021-07-27 14:07 ` Cyrill Gorcunov via Tarantool-patches
2021-07-27 14:14 ` Vladimir Davydov via Tarantool-patches
2021-07-29 22:39 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-30 8:44 ` Vladimir Davydov via Tarantool-patches
2021-07-30 22:12 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-02 7:36 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 12/20] net.box: rewrite error " Vladimir Davydov via Tarantool-patches
2021-07-30 22:13 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-02 8:00 ` Vladimir Davydov via Tarantool-patches
2021-08-02 21:47 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 13/20] net.box: rewrite send_and_recv_{iproto, console} " Vladimir Davydov via Tarantool-patches
2021-08-02 21:49 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-03 15:44 ` Vladimir Davydov via Tarantool-patches
2021-08-03 23:06 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-04 13:56 ` Vladimir Davydov via Tarantool-patches
2021-08-04 21:18 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 8:37 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 14/20] net.box: rename netbox_{prepare, encode}_request to {begin, end} Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 15/20] net.box: rewrite request implementation in C Vladimir Davydov via Tarantool-patches
2021-08-02 21:54 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-04 12:30 ` Vladimir Davydov via Tarantool-patches
2021-08-04 15:35 ` Vladimir Davydov via Tarantool-patches
2021-08-04 16:14 ` Vladimir Davydov via Tarantool-patches
2021-08-04 21:20 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 12:46 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 16/20] net.box: store next_request_id in C code Vladimir Davydov via Tarantool-patches
2021-08-03 23:06 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-04 16:25 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` Vladimir Davydov via Tarantool-patches [this message]
2021-08-03 23:07 ` [Tarantool-patches] [PATCH 17/20] net.box: rewrite console handlers in C Vladislav Shpilevoy via Tarantool-patches
2021-08-05 11:53 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 18/20] net.box: rewrite iproto " Vladimir Davydov via Tarantool-patches
2021-08-03 23:08 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 11:54 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 19/20] net.box: merge new_id, new_request and encode_method Vladimir Davydov via Tarantool-patches
2021-08-03 23:08 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 11:55 ` Vladimir Davydov via Tarantool-patches
2021-07-23 11:07 ` [Tarantool-patches] [PATCH 20/20] net.box: do not create request object in Lua for sync requests Vladimir Davydov via Tarantool-patches
2021-08-03 23:09 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-05 12:23 ` Vladimir Davydov via Tarantool-patches
2021-07-23 12:48 ` [Tarantool-patches] [PATCH 00/20] Rewrite performance critical parts of net.box in C Vladimir Davydov via Tarantool-patches
2021-07-26 7:26 ` Kirill Yukhin via Tarantool-patches
2021-07-27 9:59 ` Vladimir Davydov via Tarantool-patches
2021-07-28 22:51 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-29 11:33 ` Vladimir Davydov via Tarantool-patches
2021-07-29 15:23 ` Vladimir Davydov via Tarantool-patches
2021-07-29 22:38 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-30 10:04 ` Vladimir Davydov via Tarantool-patches
2021-07-29 22:40 ` Vladislav Shpilevoy via Tarantool-patches
2021-07-30 8:16 ` Vladimir Davydov via Tarantool-patches
2021-08-03 23:05 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-04 12:40 ` Vladimir Davydov via Tarantool-patches
2021-08-05 20:59 ` Vladislav Shpilevoy via Tarantool-patches
2021-08-09 11:22 ` Igor Munkin via Tarantool-patches
2021-08-09 11:48 ` Vitaliia Ioffe via Tarantool-patches
2021-08-09 13:56 ` Vladimir Davydov via Tarantool-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c48b13b50aea34d6199abfaa40970ab7fd1a3236.1627024646.git.vdavydov@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=vdavydov@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH 17/20] net.box: rewrite console handlers in C' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox