From: Konstantin Osipov <kostja@tarantool.org>
To: tarantool-patches@freelists.org
Cc: vdavydov.dev@gmail.com
Subject: Re: [tarantool-patches] [PATCH v2 08/10] session: introduce text box.session.push
Date: Thu, 10 May 2018 22:27:54 +0300 [thread overview]
Message-ID: <20180510192754.GH30593@atlas> (raw)
In-Reply-To: <f16c5d5a1089229efe330bf4385fdd5434be052b.1524228894.git.v.shpilevoy@tarantool.org>
* Vladislav Shpilevoy <v.shpilevoy@tarantool.org> [18/04/20 16:31]:
> +/**
> + * Push a tagged YAML document into a console socket.
> + * @param session Console session.
> + * @param port Port with YAML to push.
> + *
> + * @retval 0 Success.
> + * @retval -1 Error.
> + */
> +static int
> +console_session_push(struct session *session, struct port *port)
> +{
> + assert(session_vtab_registry[session->type].push ==
> + console_session_push);
> + uint32_t text_len;
> + const char *text = port_dump_plain(port, &text_len);
> + if (text == NULL)
> + return -1;
> + int fd = session_fd(session);
> + while (text_len > 0) {
> + while (coio_wait(fd, COIO_WRITE,
> + TIMEOUT_INFINITY) != COIO_WRITE);
Nitpick: the socket is ready in 99% of cases, there is no reason
to call coio_wait() unless you get EINTR.
Second, why the choice of fio_writev() rather than write() or
send?
What is wrong with coio_writev or similar?
> + const struct iovec iov = {
> + .iov_base = (void *) text,
> + .iov_len = text_len
> + };
> + ssize_t rc = fio_writev(fd, &iov, 1);
> + if (rc < 0)
> + return -1;
> + text_len -= rc;
> + text += rc;
> + }
> + return 0;
> +}
> @@ -92,13 +93,27 @@ local text_connection_mt = {
> --
> eval = function(self, text)
> text = text..'$EOF$\n'
> - if self:write(text) then
> + if not self:write(text) then
> + error(self:set_error())
> + end
> + while true do
> local rc = self:read()
> - if rc then
> + if not rc then
> + break
> + end
> + local handle, prefix = yaml.decode_tag(rc)
> + assert(handle or not prefix)
> + if not handle then
> + -- Can not fail - tags are encoded with no
> + -- user participation and are correct always.
> + assert(not prefix)
In Lua, asserts take CPU time. Please don't use them unless in a
test.
> return rc
> end
> + if handle == PUSH_TAG_HANDLE and self.print_f then
> + self.print_f(rc)
> + end
> end
> - error(self:set_error())
> + return rc
> end,
> --
> -- Make the connection be in error state, set error
> @@ -121,15 +136,18 @@ local text_connection_mt = {
> -- netbox-like object.
> -- @param connection Socket to wrap.
> -- @param url Parsed destination URL.
> +-- @param print_f Function to print push messages.
> +--
> -- @retval nil, err Error, and err contains an error message.
> -- @retval not nil Netbox-like object.
> --
> -local function wrap_text_socket(connection, url)
> +local function wrap_text_socket(connection, url, print_f)
> local conn = setmetatable({
> _socket = connection,
> state = 'active',
> host = url.host or 'localhost',
> port = url.service,
> + print_f = print_f,
> }, text_connection_mt)
> if not conn:write('require("console").delimiter("$EOF$")\n') or
> not conn:read() then
> @@ -369,7 +387,8 @@ local function connect(uri, opts)
> end
> local remote
> if greeting.protocol == 'Lua console' then
> - remote = wrap_text_socket(connection, u)
> + remote = wrap_text_socket(connection, u,
> + function(msg) self:print(msg) end)
> else
> opts = {
> connect_timeout = opts.timeout,
> diff --git a/src/box/lua/session.c b/src/box/lua/session.c
> index 5fe5f08d4..306271809 100644
> --- a/src/box/lua/session.c
> +++ b/src/box/lua/session.c
> @@ -41,6 +41,8 @@
> #include "box/session.h"
> #include "box/user.h"
> #include "box/schema.h"
> +#include "box/port.h"
> +#include "box/lua/console.h"
>
> static const char *sessionlib_name = "box.session";
>
> @@ -355,6 +357,52 @@ lbox_push_on_access_denied_event(struct lua_State *L, void *event)
> return 3;
> }
>
> +/**
> + * Port to push a message from Lua.
> + */
> +struct lua_push_port {
> + const struct port_vtab *vtab;
> + /**
> + * Lua state, containing data to dump on top of the stack.
> + */
> + struct lua_State *L;
> +};
> +
> +static const char *
> +lua_push_port_dump_plain(struct port *port, uint32_t *size);
> +
> +static const struct port_vtab lua_push_port_vtab = {
> + .dump_msgpack = NULL,
> + /*
> + * Dump_16 has no sense, since push appears since 1.10
> + * protocol.
> + */
> + .dump_msgpack_16 = NULL,
> + .dump_plain = lua_push_port_dump_plain,
> + .destroy = NULL,
> +};
> +
> +static const char *
> +lua_push_port_dump_plain(struct port *port, uint32_t *size)
> +{
> + struct lua_push_port *lua_port = (struct lua_push_port *) port;
> + assert(lua_port->vtab == &lua_push_port_vtab);
> + struct lua_State *L = lua_port->L;
> + int rc = console_encode_push(L);
> + if (rc == 2) {
> + assert(lua_isnil(L, -2));
> + assert(lua_isstring(L, -1));
> + diag_set(ClientError, ER_PROC_LUA, lua_tostring(L, -1));
> + return NULL;
> + }
> + assert(rc == 1);
> + assert(lua_isstring(L, -1));
> + size_t len;
> + const char *result = lua_tolstring(L, -1, &len);
> + *size = (uint32_t) len;
> + return result;
> +}
> +
> /**
> * Push a message using a protocol, depending on a session type.
> * @param data Data to push, first argument on a stack.
> @@ -367,7 +415,11 @@ lbox_session_push(struct lua_State *L)
> if (lua_gettop(L) != 1)
> return luaL_error(L, "Usage: box.session.push(data)");
>
> - if (session_push(current_session(), NULL) != 0) {
> + struct lua_push_port port;
> + port.vtab = &lua_push_port_vtab;
Why do you need a separate port?
And why do you need to create a port for every push? Can't you
reuse the same port as is used for the Lua call itself?
> + port.L = L;
> +
> + if (session_push(current_session(), (struct port *) &port) != 0) {
> lua_pushnil(L);
> luaT_pusherror(L, box_error_last());
> return 2;
> diff --git a/src/box/port.c b/src/box/port.c
> index 255eb732c..f9b655840 100644
--
Konstantin Osipov, Moscow, Russia, +7 903 626 22 32
http://tarantool.io - www.twitter.com/kostja_osipov
next prev parent reply other threads:[~2018-05-10 19:27 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-20 13:24 [PATCH v2 00/10] session: introduce box.session.push Vladislav Shpilevoy
2018-04-20 13:24 ` [PATCH v2 01/10] yaml: don't throw OOM on any error in yaml encoding Vladislav Shpilevoy
2018-05-10 18:10 ` [tarantool-patches] " Konstantin Osipov
2018-04-20 13:24 ` [tarantool-patches] [PATCH v2 10/10] session: introduce binary box.session.push Vladislav Shpilevoy
2018-05-10 19:50 ` Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-20 13:24 ` [PATCH v2 02/10] yaml: introduce yaml.encode_tagged Vladislav Shpilevoy
2018-05-10 18:22 ` [tarantool-patches] " Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-30 19:15 ` Konstantin Osipov
2018-05-30 20:49 ` Vladislav Shpilevoy
2018-05-31 10:46 ` Konstantin Osipov
2018-04-20 13:24 ` [PATCH v2 03/10] yaml: introduce yaml.decode_tag Vladislav Shpilevoy
2018-05-10 18:41 ` [tarantool-patches] " Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-05-31 10:54 ` Konstantin Osipov
2018-05-31 11:36 ` Konstantin Osipov
2018-04-20 13:24 ` [PATCH v2 04/10] console: use Lua C API to do formatting for console Vladislav Shpilevoy
2018-05-10 18:46 ` [tarantool-patches] " Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-20 13:24 ` [PATCH v2 05/10] session: move salt into iproto connection Vladislav Shpilevoy
2018-05-10 18:47 ` [tarantool-patches] " Konstantin Osipov
2018-04-20 13:24 ` [PATCH v2 06/10] session: introduce session vtab and meta Vladislav Shpilevoy
2018-05-10 19:20 ` [tarantool-patches] " Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-20 13:24 ` [PATCH v2 07/10] port: rename dump() into dump_msgpack() Vladislav Shpilevoy
2018-05-10 19:21 ` [tarantool-patches] " Konstantin Osipov
2018-04-20 13:24 ` [PATCH v2 08/10] session: introduce text box.session.push Vladislav Shpilevoy
2018-05-10 19:27 ` Konstantin Osipov [this message]
2018-05-24 20:50 ` [tarantool-patches] " Vladislav Shpilevoy
2018-04-20 13:24 ` [PATCH v2 09/10] session: enable box.session.push in local console Vladislav Shpilevoy
2018-05-10 19:28 ` [tarantool-patches] " Konstantin Osipov
2018-05-24 20:50 ` [tarantool-patches] [PATCH 1/1] netbox: introduce iterable future objects Vladislav Shpilevoy
2018-06-04 22:17 ` [tarantool-patches] " Vladislav Shpilevoy
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=20180510192754.GH30593@atlas \
--to=kostja@tarantool.org \
--cc=tarantool-patches@freelists.org \
--cc=vdavydov.dev@gmail.com \
--subject='Re: [tarantool-patches] [PATCH v2 08/10] session: introduce text box.session.push' \
/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