From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id A08046EC55; Thu, 29 Jul 2021 17:08:33 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org A08046EC55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1627567713; bh=I9msvMo7IOojBUaNFKeHTQdjr1B6vFtCn943YLNbFFc=; h=Date:To:Cc:References:In-Reply-To:Subject:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=pzauHJpocO5uD4Uua9JZH0pKwzIKsfRS59NlqEBRH6uSY1B2XAWM1Gliu48jA3iU3 GNMf5sg/uTr1Va3VfzS5UcqWHTrJpDDssRoT1VdkWry41E5NaGjqd0HMioeRtG6HfE mhW8oFCMVVO9NbdVNlhw332GzOmUcLEP1+ZNx9cY= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 4E4656EC55 for ; Thu, 29 Jul 2021 17:08:32 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 4E4656EC55 Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1m96i7-0004pc-8m; Thu, 29 Jul 2021 17:08:31 +0300 Date: Thu, 29 Jul 2021 17:08:30 +0300 To: Vladislav Shpilevoy Cc: tarantool-patches@dev.tarantool.org Message-ID: <20210729140830.5qfjs4rb33vdvwmm@esperanza> References: <9cfb84719313537a78b68083923997c5ab2e3e62.1627024646.git.vdavydov@tarantool.org> <91e6d9c8-91ab-e057-9d42-9c84ab95c89d@tarantool.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <91e6d9c8-91ab-e057-9d42-9c84ab95c89d@tarantool.org> X-4EC0790: 10 X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD941C43E597735A9C351B198F4576AC7B2770D7874BA03B4AE182A05F538085040F6CBAB350AE385C844865A3B5A233E92DBFFAE614C3CDF1E1E8ABB179E47B6C3 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7A41A3668A00E2636EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006373E8288C4653B3DD08638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D84810CA2FA2D7AC8C8FDB8651B7723A25117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8B974A882099E279BDA471835C12D1D977C4224003CC8364762BB6847A3DEAEFB0F43C7A68FF6260569E8FC8737B5C2249EC8D19AE6D49635B68655334FD4449CB9ECD01F8117BC8BEAAAE862A0553A39223F8577A6DFFEA7C837C4FEFBD186071C4224003CC83647689D4C264860C145E X-C1DE0DAB: 0D63561A33F958A54C8B799B628F5AA2EAA93E53988BCB3BA597CF830BAFB163D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA753530422897FB34C3410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D342B8615F5CFAD9D028361F98E5912B3FB3B85EC1E3537758C9E25087E95B8445D45902B12C85F84B51D7E09C32AA3244C73B4D3178970FC9F06020B30477635133E8609A02908F271FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojPp/mPgZxawEaKG0wUa3F5A== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D2896DA36E2692520998ACA2D837B3EB9274CEFED1673C562683ABF942079399BFB559BB5D741EB966A65DFF43FF7BE03240331F90058701C67EA787935ED9F1B X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH 09/20] net.box: rewrite request encoder in C X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Vladimir Davydov via Tarantool-patches Reply-To: Vladimir Davydov Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" On Thu, Jul 29, 2021 at 12:51:01AM +0200, Vladislav Shpilevoy wrote: > > diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c > > index 8952efb7bb39..49030aabea69 100644 > > --- a/src/box/lua/net_box.c > > +++ b/src/box/lua/net_box.c > > @@ -52,16 +52,34 @@ > > <...> > > > static inline size_t > > -netbox_prepare_request(lua_State *L, struct mpstream *stream, uint32_t r_type) > > +netbox_prepare_request(struct mpstream *stream, uint64_t sync, > > + enum iproto_type type) > > { > > - struct ibuf *ibuf = (struct ibuf *) lua_topointer(L, 1); > > - uint64_t sync = luaL_touint64(L, 2); > > - > > - mpstream_init(stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, > > - luamp_error, L); > > - > > /* Remember initial size of ibuf (see netbox_encode_request()) */ > > + struct ibuf *ibuf = (struct ibuf *) stream->ctx; > > 1. There is a rule now that in the new code after unary operators we > do not put whitespaces. But here you do not need a cast. In C void * to > any other pointer works implicitly. > > Here and in other new places. Removed this useless conversion here and a space after a cast operator in all patches. I wish we had a tool that would do that automatically... > > @@ -108,16 +126,15 @@ netbox_encode_request(struct mpstream *stream, size_t initial_size) > > mp_store_u32(fixheader, total_size - fixheader_size); > > } > > > > -static int > > -netbox_encode_ping(lua_State *L) > > +static void > > +netbox_encode_ping(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) > > { > > - if (lua_gettop(L) < 2) > > - return luaL_error(L, "Usage: netbox.encode_ping(ibuf, sync)"); > > - > > + (void) idx; > > struct mpstream stream; > > - size_t svp = netbox_prepare_request(L, &stream, IPROTO_PING); > > + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, > > + luamp_error, L); > > + size_t svp = netbox_prepare_request(&stream, sync, IPROTO_PING); > > 2. mpstream_init and netbox_prepare_request in 100% cases go together. > Maybe you could move the init into netbox_prepare_request? It even takes > the stream pointer already. You would only need to pass L again. Once all patches are applied, netbox_encode_auth will use a different error handler, see https://github.com/tarantool/tarantool/blob/bf2f94e9637b7028f6974cd7486e57983612c95e/src/box/lua/net_box.c#L415 But I agree that we have some code duplication because of this. We can initialize mpstream at the top level (netbox_encode_method) to eliminate it. I moved mpstream_init back to netbox_prepare_request in this patch and added a follow-up patch that moves mpstream_init to netbox_encode_method. The updated patch is below. The follow-up patch will be sent separately in reply to this email. -- >From a3a201e14439ce5a9037826256755c556c3575d0 Mon Sep 17 00:00:00 2001 From: Vladimir Davydov Date: Wed, 14 Jul 2021 18:36:27 +0300 Subject: [PATCH] net.box: rewrite request encoder in C This patch moves method_encoder table from Lua to C. This is a step towards rewriting performance-critical parts of net.box in C. Part of #6241 diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c index 8952efb7bb39..3520f56cac62 100644 --- a/src/box/lua/net_box.c +++ b/src/box/lua/net_box.c @@ -52,12 +52,32 @@ #define cfg luaL_msgpack_default +enum netbox_method { + NETBOX_PING = 0, + NETBOX_CALL_16 = 1, + NETBOX_CALL_17 = 2, + NETBOX_EVAL = 3, + NETBOX_INSERT = 4, + NETBOX_REPLACE = 5, + NETBOX_DELETE = 6, + NETBOX_UPDATE = 7, + NETBOX_UPSERT = 8, + NETBOX_SELECT = 9, + NETBOX_EXECUTE = 10, + NETBOX_PREPARE = 11, + NETBOX_UNPREPARE = 12, + NETBOX_GET = 13, + NETBOX_MIN = 14, + NETBOX_MAX = 15, + NETBOX_COUNT = 16, + NETBOX_INJECT = 17, + netbox_method_MAX +}; + static inline size_t -netbox_prepare_request(lua_State *L, struct mpstream *stream, uint32_t r_type) +netbox_prepare_request(struct lua_State *L, struct mpstream *stream, + struct ibuf *ibuf, uint64_t sync, enum iproto_type type) { - struct ibuf *ibuf = (struct ibuf *) lua_topointer(L, 1); - uint64_t sync = luaL_touint64(L, 2); - mpstream_init(stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, luamp_error, L); @@ -76,7 +96,7 @@ netbox_prepare_request(lua_State *L, struct mpstream *stream, uint32_t r_type) mpstream_encode_uint(stream, sync); mpstream_encode_uint(stream, IPROTO_REQUEST_TYPE); - mpstream_encode_uint(stream, r_type); + mpstream_encode_uint(stream, type); /* Caller should remember how many bytes was used in ibuf */ return used; @@ -108,16 +128,14 @@ netbox_encode_request(struct mpstream *stream, size_t initial_size) mp_store_u32(fixheader, total_size - fixheader_size); } -static int -netbox_encode_ping(lua_State *L) +static void +netbox_encode_ping(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 2) - return luaL_error(L, "Usage: netbox.encode_ping(ibuf, sync)"); - + (void)idx; struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_PING); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_PING); netbox_encode_request(&stream, svp); - return 0; } static int @@ -127,9 +145,12 @@ netbox_encode_auth(lua_State *L) return luaL_error(L, "Usage: netbox.encode_update(ibuf, sync, " "user, password, greeting)"); } + struct ibuf *ibuf = (struct ibuf *)lua_topointer(L, 1); + uint64_t sync = luaL_touint64(L, 2); struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_AUTH); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_AUTH); size_t user_len; const char *user = lua_tolstring(L, 3, &user_len); @@ -157,91 +178,79 @@ netbox_encode_auth(lua_State *L) return 0; } -static int -netbox_encode_call_impl(lua_State *L, enum iproto_type type) +static void +netbox_encode_call_impl(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync, + enum iproto_type type) { - if (lua_gettop(L) < 4) { - return luaL_error(L, "Usage: netbox.encode_call(ibuf, sync, " - "function_name, args)"); - } - + /* Lua stack at idx: function_name, args */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, type); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, type); mpstream_encode_map(&stream, 2); /* encode proc name */ size_t name_len; - const char *name = lua_tolstring(L, 3, &name_len); + const char *name = lua_tolstring(L, idx, &name_len); mpstream_encode_uint(&stream, IPROTO_FUNCTION_NAME); mpstream_encode_strn(&stream, name, name_len); /* encode args */ mpstream_encode_uint(&stream, IPROTO_TUPLE); - luamp_encode_tuple(L, cfg, &stream, 4); + luamp_encode_tuple(L, cfg, &stream, idx + 1); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_call_16(lua_State *L) +static void +netbox_encode_call_16(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - return netbox_encode_call_impl(L, IPROTO_CALL_16); + netbox_encode_call_impl(L, idx, ibuf, sync, IPROTO_CALL_16); } -static int -netbox_encode_call(lua_State *L) +static void +netbox_encode_call(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - return netbox_encode_call_impl(L, IPROTO_CALL); + netbox_encode_call_impl(L, idx, ibuf, sync, IPROTO_CALL); } -static int -netbox_encode_eval(lua_State *L) +static void +netbox_encode_eval(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 4) { - return luaL_error(L, "Usage: netbox.encode_eval(ibuf, sync, " - "expr, args)"); - } - + /* Lua stack at idx: expr, args */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_EVAL); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_EVAL); mpstream_encode_map(&stream, 2); /* encode expr */ size_t expr_len; - const char *expr = lua_tolstring(L, 3, &expr_len); + const char *expr = lua_tolstring(L, idx, &expr_len); mpstream_encode_uint(&stream, IPROTO_EXPR); mpstream_encode_strn(&stream, expr, expr_len); /* encode args */ mpstream_encode_uint(&stream, IPROTO_TUPLE); - luamp_encode_tuple(L, cfg, &stream, 4); + luamp_encode_tuple(L, cfg, &stream, idx + 1); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_select(lua_State *L) +static void +netbox_encode_select(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 8) { - return luaL_error(L, "Usage netbox.encode_select(ibuf, sync, " - "space_id, index_id, iterator, offset, " - "limit, key)"); - } - + /* Lua stack at idx: space_id, index_id, iterator, offset, limit, key */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_SELECT); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_SELECT); mpstream_encode_map(&stream, 6); - uint32_t space_id = lua_tonumber(L, 3); - uint32_t index_id = lua_tonumber(L, 4); - int iterator = lua_tointeger(L, 5); - uint32_t offset = lua_tonumber(L, 6); - uint32_t limit = lua_tonumber(L, 7); + uint32_t space_id = lua_tonumber(L, idx); + uint32_t index_id = lua_tonumber(L, idx + 1); + int iterator = lua_tointeger(L, idx + 2); + uint32_t offset = lua_tonumber(L, idx + 3); + uint32_t limit = lua_tonumber(L, idx + 4); /* encode space_id */ mpstream_encode_uint(&stream, IPROTO_SPACE_ID); @@ -265,100 +274,89 @@ netbox_encode_select(lua_State *L) /* encode key */ mpstream_encode_uint(&stream, IPROTO_KEY); - luamp_convert_key(L, cfg, &stream, 8); + luamp_convert_key(L, cfg, &stream, idx + 5); netbox_encode_request(&stream, svp); - return 0; } -static inline int -netbox_encode_insert_or_replace(lua_State *L, uint32_t reqtype) +static void +netbox_encode_insert_or_replace(lua_State *L, int idx, struct ibuf *ibuf, + uint64_t sync, enum iproto_type type) { - if (lua_gettop(L) < 4) { - return luaL_error(L, "Usage: netbox.encode_insert(ibuf, sync, " - "space_id, tuple)"); - } + /* Lua stack at idx: space_id, tuple */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, reqtype); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, type); mpstream_encode_map(&stream, 2); /* encode space_id */ - uint32_t space_id = lua_tonumber(L, 3); + uint32_t space_id = lua_tonumber(L, idx); mpstream_encode_uint(&stream, IPROTO_SPACE_ID); mpstream_encode_uint(&stream, space_id); /* encode args */ mpstream_encode_uint(&stream, IPROTO_TUPLE); - luamp_encode_tuple(L, cfg, &stream, 4); + luamp_encode_tuple(L, cfg, &stream, idx + 1); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_insert(lua_State *L) +static void +netbox_encode_insert(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - return netbox_encode_insert_or_replace(L, IPROTO_INSERT); + netbox_encode_insert_or_replace(L, idx, ibuf, sync, IPROTO_INSERT); } -static int -netbox_encode_replace(lua_State *L) +static void +netbox_encode_replace(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - return netbox_encode_insert_or_replace(L, IPROTO_REPLACE); + netbox_encode_insert_or_replace(L, idx, ibuf, sync, IPROTO_REPLACE); } -static int -netbox_encode_delete(lua_State *L) +static void +netbox_encode_delete(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 5) { - return luaL_error(L, "Usage: netbox.encode_delete(ibuf, sync, " - "space_id, index_id, key)"); - } - + /* Lua stack at idx: space_id, index_id, key */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_DELETE); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_DELETE); mpstream_encode_map(&stream, 3); /* encode space_id */ - uint32_t space_id = lua_tonumber(L, 3); + uint32_t space_id = lua_tonumber(L, idx); mpstream_encode_uint(&stream, IPROTO_SPACE_ID); mpstream_encode_uint(&stream, space_id); /* encode space_id */ - uint32_t index_id = lua_tonumber(L, 4); + uint32_t index_id = lua_tonumber(L, idx + 1); mpstream_encode_uint(&stream, IPROTO_INDEX_ID); mpstream_encode_uint(&stream, index_id); /* encode key */ mpstream_encode_uint(&stream, IPROTO_KEY); - luamp_convert_key(L, cfg, &stream, 5); + luamp_convert_key(L, cfg, &stream, idx + 2); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_update(lua_State *L) +static void +netbox_encode_update(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 6) { - return luaL_error(L, "Usage: netbox.encode_update(ibuf, sync, " - "space_id, index_id, key, ops)"); - } - + /* Lua stack at idx: space_id, index_id, key, ops */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_UPDATE); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_UPDATE); mpstream_encode_map(&stream, 5); /* encode space_id */ - uint32_t space_id = lua_tonumber(L, 3); + uint32_t space_id = lua_tonumber(L, idx); mpstream_encode_uint(&stream, IPROTO_SPACE_ID); mpstream_encode_uint(&stream, space_id); /* encode index_id */ - uint32_t index_id = lua_tonumber(L, 4); + uint32_t index_id = lua_tonumber(L, idx + 1); mpstream_encode_uint(&stream, IPROTO_INDEX_ID); mpstream_encode_uint(&stream, index_id); @@ -368,31 +366,27 @@ netbox_encode_update(lua_State *L) /* encode key */ mpstream_encode_uint(&stream, IPROTO_KEY); - luamp_convert_key(L, cfg, &stream, 5); + luamp_convert_key(L, cfg, &stream, idx + 2); /* encode ops */ mpstream_encode_uint(&stream, IPROTO_TUPLE); - luamp_encode_tuple(L, cfg, &stream, 6); + luamp_encode_tuple(L, cfg, &stream, idx + 3); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_upsert(lua_State *L) +static void +netbox_encode_upsert(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) != 5) { - return luaL_error(L, "Usage: netbox.encode_upsert(ibuf, sync, " - "space_id, tuple, ops)"); - } - + /* Lua stack at idx: space_id, tuple, ops */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_UPSERT); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_UPSERT); mpstream_encode_map(&stream, 4); /* encode space_id */ - uint32_t space_id = lua_tonumber(L, 3); + uint32_t space_id = lua_tonumber(L, idx); mpstream_encode_uint(&stream, IPROTO_SPACE_ID); mpstream_encode_uint(&stream, space_id); @@ -402,14 +396,13 @@ netbox_encode_upsert(lua_State *L) /* encode tuple */ mpstream_encode_uint(&stream, IPROTO_TUPLE); - luamp_encode_tuple(L, cfg, &stream, 4); + luamp_encode_tuple(L, cfg, &stream, idx + 1); /* encode ops */ mpstream_encode_uint(&stream, IPROTO_OPS); - luamp_encode_tuple(L, cfg, &stream, 5); + luamp_encode_tuple(L, cfg, &stream, idx + 2); netbox_encode_request(&stream, svp); - return 0; } static int @@ -556,61 +549,121 @@ handle_error: return 2; } -static int -netbox_encode_execute(lua_State *L) +static void +netbox_encode_execute(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 5) - return luaL_error(L, "Usage: netbox.encode_execute(ibuf, "\ - "sync, query, parameters, options)"); + /* Lua stack at idx: query, parameters, options */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_EXECUTE); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_EXECUTE); mpstream_encode_map(&stream, 3); - if (lua_type(L, 3) == LUA_TNUMBER) { - uint32_t query_id = lua_tointeger(L, 3); + if (lua_type(L, idx) == LUA_TNUMBER) { + uint32_t query_id = lua_tointeger(L, idx); mpstream_encode_uint(&stream, IPROTO_STMT_ID); mpstream_encode_uint(&stream, query_id); } else { size_t len; - const char *query = lua_tolstring(L, 3, &len); + const char *query = lua_tolstring(L, idx, &len); mpstream_encode_uint(&stream, IPROTO_SQL_TEXT); mpstream_encode_strn(&stream, query, len); } mpstream_encode_uint(&stream, IPROTO_SQL_BIND); - luamp_encode_tuple(L, cfg, &stream, 4); + luamp_encode_tuple(L, cfg, &stream, idx + 1); mpstream_encode_uint(&stream, IPROTO_OPTIONS); - luamp_encode_tuple(L, cfg, &stream, 5); + luamp_encode_tuple(L, cfg, &stream, idx + 2); netbox_encode_request(&stream, svp); - return 0; } -static int -netbox_encode_prepare(lua_State *L) +static void +netbox_encode_prepare(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) { - if (lua_gettop(L) < 3) - return luaL_error(L, "Usage: netbox.encode_prepare(ibuf, "\ - "sync, query)"); + /* Lua stack at idx: query */ struct mpstream stream; - size_t svp = netbox_prepare_request(L, &stream, IPROTO_PREPARE); + size_t svp = netbox_prepare_request(L, &stream, ibuf, sync, + IPROTO_PREPARE); mpstream_encode_map(&stream, 1); - if (lua_type(L, 3) == LUA_TNUMBER) { - uint32_t query_id = lua_tointeger(L, 3); + if (lua_type(L, idx) == LUA_TNUMBER) { + uint32_t query_id = lua_tointeger(L, idx); mpstream_encode_uint(&stream, IPROTO_STMT_ID); mpstream_encode_uint(&stream, query_id); } else { size_t len; - const char *query = lua_tolstring(L, 3, &len); + const char *query = lua_tolstring(L, idx, &len); mpstream_encode_uint(&stream, IPROTO_SQL_TEXT); mpstream_encode_strn(&stream, query, len); }; netbox_encode_request(&stream, svp); +} + +static void +netbox_encode_unprepare(lua_State *L, int idx, struct ibuf *ibuf, uint64_t sync) +{ + /* Lua stack at idx: query, parameters, options */ + netbox_encode_prepare(L, idx, ibuf, sync); +} + +static void +netbox_encode_inject(struct lua_State *L, int idx, struct ibuf *ibuf, + uint64_t sync) +{ + /* Lua stack at idx: bytes */ + (void)sync; + size_t len; + const char *data = lua_tolstring(L, idx, &len); + void *wpos = ibuf_alloc(ibuf, len); + if (wpos == NULL) + luaL_error(L, "out of memory"); + memcpy(wpos, data, len); +} + +/* + * Encodes a request for the specified method. + * + * Takes three mandatory arguments: + * - method: a value from the netbox_method enumeration + * - ibuf: buffer to write the result to + * - sync: value of the IPROTO_SYNC key + * + * Other arguments are method-specific. + */ +static int +netbox_encode_method(struct lua_State *L) +{ + typedef void (*method_encoder_f)(struct lua_State *L, int idx, + struct ibuf *ibuf, uint64_t sync); + static method_encoder_f method_encoder[] = { + [NETBOX_PING] = netbox_encode_ping, + [NETBOX_CALL_16] = netbox_encode_call_16, + [NETBOX_CALL_17] = netbox_encode_call, + [NETBOX_EVAL] = netbox_encode_eval, + [NETBOX_INSERT] = netbox_encode_insert, + [NETBOX_REPLACE] = netbox_encode_replace, + [NETBOX_DELETE] = netbox_encode_delete, + [NETBOX_UPDATE] = netbox_encode_update, + [NETBOX_UPSERT] = netbox_encode_upsert, + [NETBOX_SELECT] = netbox_encode_select, + [NETBOX_EXECUTE] = netbox_encode_execute, + [NETBOX_PREPARE] = netbox_encode_prepare, + [NETBOX_UNPREPARE] = netbox_encode_unprepare, + [NETBOX_GET] = netbox_encode_select, + [NETBOX_MIN] = netbox_encode_select, + [NETBOX_MAX] = netbox_encode_select, + [NETBOX_COUNT] = netbox_encode_call, + [NETBOX_INJECT] = netbox_encode_inject, + }; + enum netbox_method method = lua_tointeger(L, 1); + assert(method < netbox_method_MAX); + struct ibuf *ibuf = (struct ibuf *)lua_topointer(L, 2); + uint64_t sync = luaL_touint64(L, 3); + method_encoder[method](L, 4, ibuf, sync); return 0; } @@ -885,19 +938,8 @@ int luaopen_net_box(struct lua_State *L) { static const luaL_Reg net_box_lib[] = { - { "encode_ping", netbox_encode_ping }, - { "encode_call_16", netbox_encode_call_16 }, - { "encode_call", netbox_encode_call }, - { "encode_eval", netbox_encode_eval }, - { "encode_select", netbox_encode_select }, - { "encode_insert", netbox_encode_insert }, - { "encode_replace", netbox_encode_replace }, - { "encode_delete", netbox_encode_delete }, - { "encode_update", netbox_encode_update }, - { "encode_upsert", netbox_encode_upsert }, - { "encode_execute", netbox_encode_execute}, - { "encode_prepare", netbox_encode_prepare}, { "encode_auth", netbox_encode_auth }, + { "encode_method", netbox_encode_method }, { "decode_greeting",netbox_decode_greeting }, { "communicate", netbox_communicate }, { "decode_select", netbox_decode_select }, diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index a98bbfa00465..d400f92358aa 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -24,7 +24,7 @@ local check_primary_index = box.internal.check_primary_index local communicate = internal.communicate local encode_auth = internal.encode_auth -local encode_select = internal.encode_select +local encode_method = internal.encode_method local decode_greeting = internal.decode_greeting local TIMEOUT_INFINITY = 500 * 365 * 86400 @@ -111,31 +111,6 @@ local function version_at_least(peer_version_id, major, minor, patch) return peer_version_id >= version_id(major, minor, patch) end -local method_encoder = { - [M_PING] = internal.encode_ping, - [M_CALL_16] = internal.encode_call_16, - [M_CALL_17] = internal.encode_call, - [M_EVAL] = internal.encode_eval, - [M_INSERT] = internal.encode_insert, - [M_REPLACE] = internal.encode_replace, - [M_DELETE] = internal.encode_delete, - [M_UPDATE] = internal.encode_update, - [M_UPSERT] = internal.encode_upsert, - [M_SELECT] = internal.encode_select, - [M_EXECUTE] = internal.encode_execute, - [M_PREPARE] = internal.encode_prepare, - [M_UNPREPARE] = internal.encode_prepare, - [M_GET] = internal.encode_select, - [M_MIN] = internal.encode_select, - [M_MAX] = internal.encode_select, - [M_COUNT] = internal.encode_call, - [M_INJECT] = function(buf, id, bytes) -- luacheck: no unused args - local ptr = buf:reserve(#bytes) - ffi.copy(ptr, bytes, #bytes) - buf.wpos = ptr + #bytes - end -} - local method_decoder = { [M_PING] = decode_nil, [M_CALL_16] = internal.decode_select, @@ -557,7 +532,7 @@ local function create_transport(host, port, user, password, callback, worker_fiber:wakeup() end local id = next_request_id - method_encoder[method](send_buf, id, ...) + encode_method(method, send_buf, id, ...) next_request_id = next_id(id) -- Request in most cases has maximum 10 members: -- method, buffer, skip_header, id, cond, errno, response, @@ -770,7 +745,7 @@ local function create_transport(host, port, user, password, callback, 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' - method_encoder[M_INJECT](send_buf, nil, setup_delimiter) + encode_method(M_INJECT, send_buf, nil, setup_delimiter) local err, response = send_and_recv_console() if err then return error_sm(err, response) @@ -830,14 +805,16 @@ local function create_transport(host, port, user, password, callback, local select3_id local response = {} -- fetch everything from space _vspace, 2 = ITER_ALL - encode_select(send_buf, select1_id, VSPACE_ID, 0, 2, 0, 0xFFFFFFFF, nil) + encode_method(M_SELECT, send_buf, select1_id, VSPACE_ID, 0, 2, 0, + 0xFFFFFFFF, nil) -- fetch everything from space _vindex, 2 = ITER_ALL - encode_select(send_buf, select2_id, VINDEX_ID, 0, 2, 0, 0xFFFFFFFF, nil) + encode_method(M_SELECT, send_buf, select2_id, VINDEX_ID, 0, 2, 0, + 0xFFFFFFFF, nil) -- fetch everything from space _vcollation, 2 = ITER_ALL if peer_has_vcollation then select3_id = new_request_id() - encode_select(send_buf, select3_id, VCOLLATION_ID, 0, 2, 0, - 0xFFFFFFFF, nil) + encode_method(M_SELECT, send_buf, select3_id, VCOLLATION_ID, + 0, 2, 0, 0xFFFFFFFF, nil) end schema_version = nil -- any schema_version will do provided that