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