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 9FF796EC5A; Fri, 23 Jul 2021 14:12:03 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 9FF796EC5A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1627038723; bh=qrQte8C48Nh6RxBXclioxo9v2q/7XxWhUvbxbvnkA4k=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=mpWxykXtePQauPj9kpL8dR9RsLAVQS6TWy5Cautja/rwdGIgnCvjD4V1LchvHtRCg 0ZLGXLON9K1xSHYNeqnW5iWihH0RatZS4meJlOfGKu6A6Q2ILKvz+9uCpCYpJDloEy 88dqDZl/5SuJqDn+5hX/23MJqts/TVxafsTyXmfA= 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 DB85E6EC5A for ; Fri, 23 Jul 2021 14:07:42 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DB85E6EC5A Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1m6t1n-0004dl-N5; Fri, 23 Jul 2021 14:07:42 +0300 To: tarantool-patches@dev.tarantool.org Date: Fri, 23 Jul 2021 14:07:19 +0300 Message-Id: <9cfb84719313537a78b68083923997c5ab2e3e62.1627024646.git.vdavydov@tarantool.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-174C08C4: 5188C02AEC42908C481ED7ADC579193296BBA28369E3F2D2713F3D5F7D406D31BCF678C7329BA986 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD941C43E597735A9C3038391AAE5FBFA76FBCFDED1455B43CD182A05F538085040BE4C896D889F01533B6B2596139F1B37824F9840E84B219E50B4C5FC9A9A0D7C X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7EC5C31BCB549C52BEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006371758572763D318798638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8C876A2ADF6EB9E4573C49531E781A6F2117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BF1175FABE1C0F9B6A471835C12D1D977C4224003CC8364762BB6847A3DEAEFB0F43C7A68FF6260569E8FC8737B5C2249EC8D19AE6D49635B68655334FD4449CB9ECD01F8117BC8BEAAAE862A0553A39223F8577A6DFFEA7C799A55B1B7C3DAF143847C11F186F3C59DAA53EE0834AAEE X-C1DE0DAB: 8BD88D57C5CADBC8B2710865C3867510A0B4543D0F65078DA3B1A56EE2B804F6B226C914C996894645FD9D8A29397D6EFF55FE49A3C2BFCFC8C84E951CD0BE2F296C473AB1E14218EA052B563B0B06C67866D6147AF826D8C876A2ADF6EB9E4573C49531E781A6F2F972CCD2F8FE1EF1CFC4036BBF6A4EA91D7B6CCDEC98EA79CB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D342B94C1DAF75C4D223AE29C52D32FF6ED5C7C35248E3C13BE6A0DC198238EDC24194A587B2CD8D0301D7E09C32AA3244CBF97554059E6C993EEB085EEA8570FA705AB220A9D022EBC729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojbL9S8ysBdXiEX0g4jkpDtaaB82f7VmAk X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5DCE334D491F35DBA7ABA22E401D6927C1274CEFED1673C562683ABF942079399BFB559BB5D741EB966A65DFF43FF7BE03240331F90058701C67EA787935ED9F1B X-Mras: Ok Subject: [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" This patch moves method_encoder table from Lua to C. This is a step towards rewriting performance-critical parts of net.box in C. --- src/box/lua/net_box.c | 345 +++++++++++++++++++++++----------------- src/box/lua/net_box.lua | 41 ++--- 2 files changed, 208 insertions(+), 178 deletions(-) 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 @@ #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 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; size_t used = ibuf_used(ibuf); /* Reserve and skip space for fixheader */ @@ -76,7 +94,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 +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); netbox_encode_request(&stream, svp); - return 0; } static int @@ -127,9 +144,13 @@ 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, sync, IPROTO_AUTH); size_t user_len; const char *user = lua_tolstring(L, 3, &user_len); @@ -157,91 +178,83 @@ 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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 +278,93 @@ 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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 +374,28 @@ 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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 +405,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 +558,123 @@ 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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); + mpstream_init(&stream, ibuf, ibuf_reserve_cb, ibuf_alloc_cb, + luamp_error, L); + size_t svp = netbox_prepare_request(&stream, 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 +949,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 76cfd40e3bee..bb844184fa01 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.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 -- 2.25.1