From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTP id 93EEC24756 for ; Tue, 15 May 2018 14:31:23 -0400 (EDT) Received: from turing.freelists.org ([127.0.0.1]) by localhost (turing.freelists.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id wZdM_OYY5LsQ for ; Tue, 15 May 2018 14:31:23 -0400 (EDT) Received: from smtp63.i.mail.ru (smtp63.i.mail.ru [217.69.128.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by turing.freelists.org (Avenir Technologies Mail Multiplex) with ESMTPS id 301DF24746 for ; Tue, 15 May 2018 14:31:23 -0400 (EDT) Subject: [tarantool-patches] Re: [PATCH 1/1] netbox: optimize body decoding From: Vladislav Shpilevoy References: Message-ID: <96c959dc-6275-667c-44a8-8a6faa271e75@tarantool.org> Date: Tue, 15 May 2018 21:31:20 +0300 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset="utf-8"; format="flowed" Content-Language: en-US Content-Transfer-Encoding: 8bit Sender: tarantool-patches-bounce@freelists.org Errors-to: tarantool-patches-bounce@freelists.org Reply-To: tarantool-patches@freelists.org List-help: List-unsubscribe: List-software: Ecartis version 1.0.0 List-Id: tarantool-patches List-subscribe: List-owner: List-post: List-archive: To: tarantool-patches@freelists.org Cc: kostja@tarantool.org Hello. > Константин Осипов, [15 мая 2018 г., 21:16:08]: > я всё же считаю что у decode_body должна быть такая же сигнатура как у decode > > вот эта проверка должна быть снаружи: > > + if (data != end) > + return luaL_error(L, "invalid xrow length"); > > и сообщение кривое > > это не xrow length > > это body length Below the fix is presented. At the end of the letter the whole patch is attached. diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c index 3d9479283..adf5f7603 100644 --- a/src/box/lua/net_box.c +++ b/src/box/lua/net_box.c @@ -560,14 +560,13 @@ handle_error: * Decode Tarantool response body. * @param Lua stack[1] Raw MessagePack pointer. * @param Lua stack[2] End of body pointer. - * @retval Decoded body. + * @retval Decoded body and position of the body end. */ static int netbox_decode_body(struct lua_State *L) { uint32_t ctypeid; const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid); - const char *end = *(const char **)luaL_checkcdata(L, 2, &ctypeid); assert(mp_typeof(*data) == MP_MAP); uint32_t map_size = mp_decode_map(&data); /* Until 2.0 body has no keys except DATA. */ @@ -591,9 +590,8 @@ netbox_decode_body(struct lua_State *L) } } } - if (data != end) - return luaL_error(L, "invalid xrow length"); - return 1; + *(const char **)luaL_pushcdata(L, ctypeid) = data; + return 2; } int diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 194a1c86b..8fcaf89e8 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -49,29 +49,30 @@ local E_PROC_LUA = box.error.PROC_LUA -- utility tables local is_final_state = {closed = 1, error = 1} -local function decode_nil(...) end -local function decode_data(raw_data, raw_data_end) - local response, real_end = decode(raw_data) - assert(real_end == raw_data_end, "invalid xrow length") - return response[IPROTO_DATA_KEY] +local function decode_nil(raw_data, raw_data_end) + return nil, raw_data_end end -local function decode_tuple(raw_data, raw_data_end) - return internal.decode_body(raw_data, raw_data_end)[1] +local function decode_data(raw_data) + local response, raw_end = decode(raw_data) + return response[IPROTO_DATA_KEY], raw_end end -local function decode_get(raw_data, raw_data_end) - local body = internal.decode_body(raw_data, raw_data_end) +local function decode_tuple(raw_data) + local response, raw_end = internal.decode_body(raw_data) + return response[1], raw_end +end +local function decode_get(raw_data) + local body, raw_end = internal.decode_body(raw_data) if body[2] then - return nil, box.error.MORE_THAN_ONE_TUPLE + return nil, raw_end, box.error.MORE_THAN_ONE_TUPLE end - return body[1] + return body[1], raw_end end -local function decode_select(raw_data, raw_data_end) - return internal.decode_body(raw_data, raw_data_end) +local function decode_select(raw_data) + return internal.decode_body(raw_data) end -local function decode_count(raw_data, raw_data_end) - local response, real_end = decode(raw_data) - assert(real_end == raw_data_end, "invalid xrow length") - return response[IPROTO_DATA_KEY][1] +local function decode_count(raw_data) + local response, raw_end = decode(raw_data) + return response[IPROTO_DATA_KEY][1], raw_end end local method_encoder = { @@ -467,8 +468,10 @@ local function create_transport(host, port, user, password, callback, end -- Decode xrow.body[DATA] to Lua objects - request.response, request.errno = + local real_end + request.response, real_end, request.errno = method_decoder[request.method](body_rpos, body_end) + assert(real_end == body_end, "invalid body length") request.cond:broadcast() end =========================================================================================== diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c index 04fe70b03..adf5f7603 100644 --- a/src/box/lua/net_box.c +++ b/src/box/lua/net_box.c @@ -38,6 +38,7 @@ #include "box/iproto_constants.h" #include "box/lua/tuple.h" /* luamp_convert_tuple() / luamp_convert_key() */ #include "box/xrow.h" +#include "box/tuple.h" #include "lua/msgpack.h" #include "third_party/base64.h" @@ -555,6 +556,44 @@ handle_error: return 2; } +/** + * Decode Tarantool response body. + * @param Lua stack[1] Raw MessagePack pointer. + * @param Lua stack[2] End of body pointer. + * @retval Decoded body and position of the body end. + */ +static int +netbox_decode_body(struct lua_State *L) +{ + uint32_t ctypeid; + const char *data = *(const char **)luaL_checkcdata(L, 1, &ctypeid); + assert(mp_typeof(*data) == MP_MAP); + uint32_t map_size = mp_decode_map(&data); + /* Until 2.0 body has no keys except DATA. */ + assert(map_size == 1); + for (uint32_t i = 0; i < map_size; ++i) { + uint32_t key = mp_decode_uint(&data); + if (key == IPROTO_DATA) { + uint32_t count = mp_decode_array(&data); + lua_createtable(L, count, 0); + struct tuple_format *format = + box_tuple_format_default(); + for (uint32_t j = 0; j < count; ++j) { + const char *begin = data; + mp_next(&data); + struct tuple *tuple = + box_tuple_new(format, begin, data); + if (tuple == NULL) + luaT_error(L); + luaT_pushtuple(L, tuple); + lua_rawseti(L, -2, j + 1); + } + } + } + *(const char **)luaL_pushcdata(L, ctypeid) = data; + return 2; +} + int luaopen_net_box(struct lua_State *L) { @@ -572,6 +611,7 @@ luaopen_net_box(struct lua_State *L) { "encode_auth", netbox_encode_auth }, { "decode_greeting",netbox_decode_greeting }, { "communicate", netbox_communicate }, + { "decode_body", netbox_decode_body }, { NULL, NULL} }; /* luaL_register_module polutes _G */ diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 46382129f..8fcaf89e8 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -27,7 +27,6 @@ local encode_auth = internal.encode_auth local encode_select = internal.encode_select local decode_greeting = internal.decode_greeting -local sequence_mt = { __serialize = 'sequence' } local TIMEOUT_INFINITY = 500 * 365 * 86400 local VSPACE_ID = 281 local VINDEX_ID = 289 @@ -50,31 +49,30 @@ local E_PROC_LUA = box.error.PROC_LUA -- utility tables local is_final_state = {closed = 1, error = 1} -local function decode_nil(...) end -local function decode_nop(...) return ... end -local function decode_tuple(response) - if response[1] then - return box.tuple.new(response[1]) - end +local function decode_nil(raw_data, raw_data_end) + return nil, raw_data_end end -local function decode_get(response) - if response[2] then - return nil, box.error.MORE_THAN_ONE_TUPLE - end - if response[1] then - return box.tuple.new(response[1]) - end +local function decode_data(raw_data) + local response, raw_end = decode(raw_data) + return response[IPROTO_DATA_KEY], raw_end end -local function decode_select(response) - setmetatable(response, sequence_mt) - local tnew = box.tuple.new - for i, v in pairs(response) do - response[i] = tnew(v) +local function decode_tuple(raw_data) + local response, raw_end = internal.decode_body(raw_data) + return response[1], raw_end +end +local function decode_get(raw_data) + local body, raw_end = internal.decode_body(raw_data) + if body[2] then + return nil, raw_end, box.error.MORE_THAN_ONE_TUPLE end - return response + return body[1], raw_end +end +local function decode_select(raw_data) + return internal.decode_body(raw_data) end -local function decode_count(response) - return response[1] +local function decode_count(raw_data) + local response, raw_end = decode(raw_data) + return response[IPROTO_DATA_KEY][1], raw_end end local method_encoder = { @@ -103,8 +101,8 @@ local method_encoder = { local method_decoder = { ping = decode_nil, call_16 = decode_select, - call_17 = decode_nop, - eval = decode_nop, + call_17 = decode_data, + eval = decode_data, insert = decode_tuple, replace = decode_tuple, delete = decode_tuple, @@ -115,7 +113,7 @@ local method_decoder = { min = decode_get, max = decode_get, count = decode_count, - inject = decode_nop, + inject = decode_data, } local function next_id(id) return band(id + 1, 0x7FFFFFFF) end @@ -470,12 +468,10 @@ local function create_transport(host, port, user, password, callback, end -- Decode xrow.body[DATA] to Lua objects - body, body_end_check = decode(body_rpos) - assert(body_end == body_end_check, "invalid xrow length") - if body and body[IPROTO_DATA_KEY] then - request.response, request.errno = - method_decoder[request.method](body[IPROTO_DATA_KEY]) - end + local real_end + request.response, real_end, request.errno = + method_decoder[request.method](body_rpos, body_end) + assert(real_end == body_end, "invalid body length") request.cond:broadcast() end diff --git a/test/box/call.result b/test/box/call.result index e27e2127d..40d7ef952 100644 --- a/test/box/call.result +++ b/test/box/call.result @@ -632,7 +632,7 @@ conn:eval("return return_sparse1()") ... conn:call_16("return_sparse1") --- -- - [{20: 1, 1: 1}] +- - [{1: 1, 20: 1}] ... function return_sparse2() return { [1] = 1, [20] = 1} end ---