From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org, Konstantin Osipov <kostja@tarantool.org> Subject: [tarantool-patches] Re: [PATCH 4/8] netbox: extend codec with 'decode' methods Date: Tue, 8 May 2018 20:24:33 +0300 [thread overview] Message-ID: <57cef482-d13b-d0d8-7f3c-a58e601e796c@tarantool.org> (raw) In-Reply-To: <20180508154934.GD4867@atlas> Hello. Thanks for review. On 08/05/2018 18:49, Konstantin Osipov wrote: > * Vladislav Shpilevoy <v.shpilevoy@tarantool.org> [18/04/16 21:44]: >> Netbox has a table 'method_codec' that is used to encode a >> request by a method name. But a response is decoded out of codec. >> It leads to >> 1) decoding into Lua tables before decoding into tuples where >> needed - it is double decoding and produces a lot of garbage; >> 2) each method contains hacks like one_tuple(), or single tuple >> check. >> >> These things can not be fixed with no real codec instead of >> encoder only. >> >> Also global table with decoders is needed for #3107, where >> a request could be sent async with no fiber blocking. An async >> response when received already does not have a call context - it >> has only method name. >> >> Needed for #3107 >> --- >> src/box/lua/net_box.lua | 116 +++++++++++++++++++++++++++++------------------- >> test/box/net.box.result | 14 ++++++ >> test/box/sql.result | 2 + >> 3 files changed, 87 insertions(+), 45 deletions(-) >> >> diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua >> index 4ed2b375d..3868cdf1c 100644 >> --- a/src/box/lua/net_box.lua >> +++ b/src/box/lua/net_box.lua >> @@ -50,7 +50,34 @@ local E_PROC_LUA = box.error.PROC_LUA >> >> -- utility tables >> local is_final_state = {closed = 1, error = 1} >> -local method_codec = { >> + >> +local function decode_nil(...) end >> +local function decode_nothing(...) return ... end > > decode_nothing -> decode_nop You reviewed the old patch. Is is fixed already on Vova request. > >> +local function decode_one_tuple(response) >> + if response[1] then >> + return box.tuple.new(response[1]) >> + end >> +end > > decode_one_tuple -> decode_tuple Ok. @@ -53,7 +53,7 @@ local is_final_state = {closed = 1, error = 1} local function decode_nil(...) end local function decode_nop(...) return ... end -local function decode_one_tuple(response) +local function decode_tuple(response) if response[1] then return box.tuple.new(response[1]) end @@ -105,10 +105,10 @@ local method_decoder = { call_16 = decode_select, call_17 = decode_nop, eval = decode_nop, - insert = decode_one_tuple, - replace = decode_one_tuple, - delete = decode_one_tuple, - update = decode_one_tuple, + insert = decode_tuple, + replace = decode_tuple, + delete = decode_tuple, + update = decode_tuple, upsert = decode_nil, select = decode_select, get = decode_unique_tuple, > > Why do you need the if () guard? Body can be empty - in such a case there is no sense to allocate cdata. > >> +local function decode_single_tuple(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 >> +end > > decode_single_tuple -> decode_get() Ok. @@ -58,7 +58,7 @@ local function decode_tuple(response) return box.tuple.new(response[1]) end end -local function decode_unique_tuple(response) +local function decode_get(response) if response[2] then return nil, box.error.MORE_THAN_ONE_TUPLE end @@ -111,9 +111,9 @@ local method_decoder = { update = decode_tuple, upsert = decode_nil, select = decode_select, - get = decode_unique_tuple, - min = decode_unique_tuple, - max = decode_unique_tuple, + get = decode_get, + min = decode_get, + max = decode_get, count = decode_count, inject = decode_nop, > >> +local function decode_select(response) >> + setmetatable(response, sequence_mt) >> + for i, v in pairs(response) do >> + response[i] = box.tuple.new(v) >> + end >> + return response >> +end > > Why are you using pairs() rather than ipairs()? Pairs is faster. https://stackoverflow.com/questions/8955085/should-i-use-ipairs-or-a-for-loop > > How does this avoid double decode as you claim in changeset > comment? In no way. I did not said, that I fix it here. I just note, that it is a problem, solution of which requires separate decoders. > >> +local function decode_count(response) >> + return response[1] >> +end >> + >> @@ -336,7 +385,10 @@ local function create_transport(host, port, user, password, callback, >> -- Decode xrow.body[DATA] to Lua objects >> body, body_end_check = decode(body_rpos) >> assert(body_end == body_end_check, "invalid xrow length") >> - return res -- the length of xrow.body >> - elseif not err then >> - setmetatable(res, sequence_mt) >> - local postproc = method ~= 'eval' and method ~= 'call_17' >> - if postproc then >> - local tnew = box.tuple.new > > You removed this local variable from the decoder - it was here > for a reason. Please put it back in your implementation of decoder. Ok. @@ -68,8 +68,9 @@ local function decode_unique_tuple(response) end local function decode_select(response) setmetatable(response, sequence_mt) + local tnew box.tuple.new for i, v in pairs(response) do - response[i] = box.tuple.new(v) + response[i] = tnew(v) end return response end > >> diff --git a/test/box/net.box.result b/test/box/net.box.result >> index cf7b27f0b..6a3713fc0 100644 >> --- a/test/box/net.box.result >> +++ b/test/box/net.box.result >> @@ -416,9 +416,11 @@ cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) >> ... >> cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) >> --- >> +- null > > net.box calling convention should be the same as local box, if a > tuple is not found, it should return nothing, not null. > Ok. diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua index 0e2485f66..f6eef56fb 100644 --- a/src/box/lua/net_box.lua +++ b/src/box/lua/net_box.lua @@ -68,7 +68,7 @@ local function decode_get(response) end local function decode_select(response) setmetatable(response, sequence_mt) - local tnew box.tuple.new + local tnew = box.tuple.new for i, v in pairs(response) do response[i] = tnew(v) end @@ -1099,6 +1099,12 @@ function console_methods:eval(line, timeout) return res[1] or res end +local function nothing_or_data(value) + if value ~= nil then + return value + end +end + space_metatable = function(remote) local methods = {} @@ -1129,7 +1135,8 @@ space_metatable = function(remote) function methods:upsert(key, oplist, opts) check_space_arg(self, 'upsert') - return remote:_request('upsert', opts, self.id, key, oplist) + return nothing_or_data(remote:_request('upsert', opts, self.id, key, + oplist)) end function methods:get(key, opts) @@ -1167,8 +1174,8 @@ index_metatable = function(remote) if opts and opts.buffer then error("index:get() doesn't support `buffer` argument") end - return remote:_request('get', opts, self.space.id, self.id, - box.index.EQ, 0, 2, key) + return nothing_or_data(remote:_request('get', opts, self.space.id, + self.id, box.index.EQ, 0, 2, key)) end function methods:min(key, opts) @@ -1176,8 +1183,9 @@ index_metatable = function(remote) if opts and opts.buffer then error("index:min() doesn't support `buffer` argument") end - return remote:_request('min', opts, self.space.id, self.id, - box.index.GE, 0, 1, key) + return nothing_or_data(remote:_request('min', opts, self.space.id, + self.id, box.index.GE, 0, 1, + key)) end function methods:max(key, opts) @@ -1185,8 +1193,9 @@ index_metatable = function(remote) if opts and opts.buffer then error("index:max() doesn't support `buffer` argument") end - return remote:_request('max', opts, self.space.id, self.id, - box.index.LE, 0, 1, key) + return nothing_or_data(remote:_request('max', opts, self.space.id, + self.id, box.index.LE, 0, 1, + key)) end function methods:count(key, opts) @@ -1201,13 +1210,14 @@ index_metatable = function(remote) function methods:delete(key, opts) check_index_arg(self, 'delete') - return remote:_request('delete', opts, self.space.id, self.id, key) + return nothing_or_data(remote:_request('delete', opts, self.space.id, + self.id, key)) end function methods:update(key, oplist, opts) check_index_arg(self, 'update') - return remote:_request('update', opts, self.space.id, self.id, key, - oplist) + return nothing_or_data(remote:_request('update', opts, self.space.id, + self.id, key, oplist)) end return { __index = methods, __metatable = false } diff --git a/test/box/net.box.result b/test/box/net.box.result index 6a3713fc0..4fbc70ec6 100644 --- a/test/box/net.box.result +++ b/test/box/net.box.result @@ -416,11 +416,9 @@ cn.space.net_box_test_space:select({234}, { iterator = 'LT' }) ... cn.space.net_box_test_space:update({1}, { { '+', 2, 2 } }) --- -- null ... cn.space.net_box_test_space:delete{1} --- -- null ... cn.space.net_box_test_space:delete{2} --- @@ -428,7 +426,6 @@ cn.space.net_box_test_space:delete{2} ... cn.space.net_box_test_space:delete{2} --- -- null ... -- test one-based indexing in splice operation (see update.test.lua) cn.space.net_box_test_space:replace({10, 'abcde'}) @@ -757,15 +754,12 @@ remote_space:upsert({3}, {}, { timeout = 1e-9 }) ... remote_space:upsert({4}, {}) --- -- null ... remote_space:upsert({5}, {}, { timeout = 1.00 }) --- -- null ... remote_space:upsert({3}, {}) --- -- null ... remote_space:update({3}, {}, { timeout = 1e-9 }) --- @@ -987,15 +981,12 @@ _ = remote_pk:delete({5}) ... remote_space:get(0) --- -- null ... remote_space:get(1) --- -- null ... remote_space:get(2) --- -- null ... remote_space = nil --- @@ -1327,7 +1318,6 @@ c.space.test:select{} ... c.space.test:upsert({1, 2, 'nothing'}, {{'+', 2, 1}}) -- common update --- -- null ... c.space.test:select{} --- @@ -1335,7 +1325,6 @@ c.space.test:select{} ... c.space.test:upsert({2, 4, 'something'}, {{'+', 2, 1}}) -- insert --- -- null ... c.space.test:select{} --- @@ -1344,7 +1333,6 @@ c.space.test:select{} ... c.space.test:upsert({2, 4, 'nothing'}, {{'+', 3, 100500}}) -- wrong operation --- -- null ... c.space.test:select{} --- diff --git a/test/box/sql.result b/test/box/sql.result index 95f8da7dd..11a698850 100644 --- a/test/box/sql.result +++ b/test/box/sql.result @@ -105,7 +105,6 @@ space:select{1} -- xxx: update comes through, returns 0 rows affected space:update(1, {{'=', 2, 'I am a new tuple'}}) --- -- null ... -- nothing is selected, since nothing was there space:select{1} @@ -209,7 +208,6 @@ space:delete(0) ... space:delete(4294967295) --- -- null ... box.space.test:drop() ---
next prev parent reply other threads:[~2018-05-08 17:24 UTC|newest] Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-04-16 18:39 [PATCH 0/8] netbox: introduce fiber-async API Vladislav Shpilevoy 2018-04-16 18:39 ` [PATCH 1/8] lua: fix box.error.raise Vladislav Shpilevoy 2018-04-23 16:19 ` Vladimir Davydov 2018-05-08 15:36 ` [tarantool-patches] " Konstantin Osipov 2018-05-08 17:24 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-16 18:39 ` [PATCH 2/8] lua: allow to create and error object with no throw Vladislav Shpilevoy 2018-04-23 16:20 ` Vladimir Davydov 2018-05-08 15:37 ` [tarantool-patches] " Konstantin Osipov 2018-04-16 18:39 ` [PATCH 3/8] console: fix a bug in interactive readline usage Vladislav Shpilevoy 2018-04-23 16:20 ` Vladimir Davydov 2018-05-08 15:37 ` [tarantool-patches] " Konstantin Osipov 2018-04-16 18:39 ` [PATCH 4/8] netbox: extend codec with 'decode' methods Vladislav Shpilevoy 2018-04-23 16:42 ` Vladimir Davydov 2018-04-23 18:59 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-24 13:16 ` Vladimir Davydov 2018-05-08 15:49 ` [tarantool-patches] " Konstantin Osipov 2018-05-08 17:24 ` Vladislav Shpilevoy [this message] 2018-04-16 18:39 ` [PATCH 5/8] test: fix unstable test Vladislav Shpilevoy 2018-04-22 5:32 ` [tarantool-patches] " Kirill Yukhin 2018-05-08 15:50 ` Konstantin Osipov 2018-04-16 18:39 ` [PATCH 6/8] netbox: introduce fiber-async API Vladislav Shpilevoy 2018-04-23 12:31 ` [tarantool-patches] " Alexander Turenko 2018-04-23 18:59 ` Vladislav Shpilevoy 2018-04-23 16:44 ` Vladimir Davydov 2018-04-23 18:59 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-24 13:05 ` Vladimir Davydov 2018-04-16 18:39 ` [PATCH 7/8] netbox: remove schema_version from requests Vladislav Shpilevoy 2018-05-08 16:06 ` [tarantool-patches] " Konstantin Osipov 2018-05-08 17:24 ` [tarantool-patches] " Vladislav Shpilevoy 2018-04-16 18:39 ` [PATCH 8/8] netbox: implement perform_request via async version Vladislav Shpilevoy 2018-04-23 16:47 ` Vladimir Davydov 2018-04-23 19:00 ` [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=57cef482-d13b-d0d8-7f3c-a58e601e796c@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='[tarantool-patches] Re: [PATCH 4/8] netbox: extend codec with '\''decode'\'' methods' \ /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