diff --git a/src/lua/box_net_box.lua b/src/lua/box_net_box.lua index 870d049fda884118d19e6d505c402ce3934f7a19..67cef788e5544882bfac18e4787e551d1cc79d47 100644 --- a/src/lua/box_net_box.lua +++ b/src/lua/box_net_box.lua @@ -40,20 +40,18 @@ local GREETING_SIZE = 128 local TIMEOUT_INFINITY = 500 * 365 * 86400 -local sequence_mt = { __serialize = 'sequence'} -local mapping_mt = { __serialize = 'mapping'} +local sequence_mt = { __serialize = 'sequence' } +local mapping_mt = { __serialize = 'mapping' } local CONSOLE_FAKESYNC = 15121974 local function request(header, body) - -- hint msgpack to always encode header and body as a map header = msgpack.encode(setmetatable(header, mapping_mt)) body = msgpack.encode(setmetatable(body, mapping_mt)) local len = msgpack.encode(string.len(header) + string.len(body)) - return len .. header .. body end @@ -158,8 +156,7 @@ local proto = { end, -- select - select = function(sync, spaceno, indexno, key, opts) - + select = function(sync, spaceno, indexno, key, opts) if opts == nil then opts = {} end @@ -358,7 +355,7 @@ local remote_methods = { end if port == nil then - + local address = urilib.parse(tostring(host)) if address == nil or address.service == nil then box.error(box.error.PROC_LUA, @@ -391,7 +388,7 @@ local remote_methods = { box.error(box.error.PROC_LUA, "net.box: user is not defined") end - + if self.host == nil then self.host = 'localhost' @@ -451,7 +448,7 @@ local remote_methods = { local res = self:_request('call', true, proc_name, {...}) return res.body[DATA] end - + local eval_str = proc_name .. '(' for i = 1, select('#', ...) do if i > 1 then @@ -517,6 +514,10 @@ local remote_methods = { } end, + reload_schema = function(self) + self:_load_schema() + end, + close = function(self) if self.state ~= 'closed' then self:_switch_state('closed') @@ -582,7 +583,7 @@ local remote_methods = { if result ~= nil then result = result[1] end - + local hdr = { [SYNC] = CONSOLE_FAKESYNC, [TYPE] = 0 } local body = {} @@ -611,7 +612,7 @@ local remote_methods = { if self.console then return self:_check_console_response(self) end - + while true do if #self.rbuf < 5 then break @@ -762,12 +763,12 @@ local remote_methods = { if not s then self:_fatal(e) end - + xpcall(function() self:_load_schema() end, function(e) log.info("Can't load schema: %s", tostring(e)) end) - + if self.state ~= 'error' and self.state ~= 'closed' then self:_switch_state('active') end @@ -779,11 +780,11 @@ local remote_methods = { _auth = function(self) if self.opts.user == nil or self.opts.password == nil then - self:_switch_state 'authen' + self:_switch_state('authen') return end - self:_switch_state 'auth' + self:_switch_state('auth') local auth_res = self:_request_internal('auth', false, self.opts.user, self.opts.password, self.handshake) @@ -793,7 +794,7 @@ local remote_methods = { return end - self:_switch_state 'authen' + self:_switch_state('authen') end, -- states wakeup _read_worker @@ -821,13 +822,12 @@ local remote_methods = { return false end, - _load_schema = function(self) - if self.state ~= 'authen' then - self:_fatal 'Can not load schema from the state' + if self.state == 'closed' or self.state == 'error' then + self:_fatal('Can not load schema from the state') return end - + self:_switch_state('schema') local spaces = self:_request_internal('select', @@ -837,7 +837,6 @@ local remote_methods = { local sl = {} - for _, space in pairs(spaces) do local name = space[3] local id = space[1] @@ -851,7 +850,6 @@ local remote_methods = { field_count = field_count, enabled = true, index = {} - } if #space > 5 and string.match(space[6], 'temporary') then s.temporary = true @@ -863,7 +861,6 @@ local remote_methods = { sl[id] = s sl[name] = s - end for _, index in pairs(indexes) do @@ -941,7 +938,7 @@ local remote_methods = { fiber.name('net.box.write') while self.state ~= 'closed' do self:_wait_state(self._rw_states) - + if self.state == 'closed' then break end @@ -1017,7 +1014,7 @@ local remote_methods = { end, _request_raw = function(self, sync, request, raise) - + local fid = fiber.id() if self.timeouts[fid] == nil then self.timeouts[fid] = TIMEOUT_INFINITY @@ -1052,7 +1049,7 @@ local remote_methods = { if raise and response.hdr[TYPE] ~= OK then box.error({ - code = response.hdr[TYPE], + code = bit.band(response.hdr[TYPE], bit.lshift(1, 15) - 1), reason = response.body[ERROR] }) end @@ -1072,11 +1069,9 @@ local remote_methods = { end, _request_internal = function(self, name, raise, ...) - local sync = self.proto:sync() local request = self.proto[name](sync, ...) return self:_request_raw(sync, request, raise) - end, -- private (low level) methods @@ -1110,6 +1105,7 @@ setmetatable(remote, { __index = remote_methods }) remote.self = { ping = function() return true end, + reload_schema = function() end, close = function() end, timeout = function(self) return self end, wait_connected = function(self) return true end, @@ -1151,5 +1147,3 @@ setmetatable(remote.self, { }) return remote - - diff --git a/src/lua/digest.lua b/src/lua/digest.lua index 3f5653be86145e88d8f376ed21873dc58ee1faef..1e41483f6622795b1e4d47b870e3fdc2edae0041 100644 --- a/src/lua/digest.lua +++ b/src/lua/digest.lua @@ -35,6 +35,7 @@ ffi.cdef[[ local ssl if ssl == nil then local variants = { + 'libssl.so.10', 'libssl.so.1.0.0', 'libssl.so.0.9.8', 'libssl.so', diff --git a/test/box/box.net.box.result b/test/box/box.net.box.result index b5af04d8a7ccdcf38bd52825ff6c8794d3a88125..3d0a204c5d6e15220e9209cde6544f09144a55e9 100644 --- a/test/box/box.net.box.result +++ b/test/box/box.net.box.result @@ -648,3 +648,116 @@ end; gh594() --- ... +-- #636: Reload schema on demand +sp = box.schema.create_space('test_old') +--- +... +sp:create_index('primary') +--- +- unique: true + parts: + - type: NUM + fieldno: 1 + id: 0 + space_id: 512 + name: primary + type: TREE +... +sp:insert{1, 2, 3} +--- +- [1, 2, 3] +... +con = remote.new(box.cfg.listen) +--- +... +con:ping() +--- +- true +... +con.space.test_old:select{} +--- +- - [1, 2, 3] +... +con.space.test == nil +--- +- true +... +sp = box.schema.create_space('test') +--- +... +sp:create_index('primary') +--- +- unique: true + parts: + - type: NUM + fieldno: 1 + id: 0 + space_id: 513 + name: primary + type: TREE +... +sp:insert{2, 3, 4} +--- +- [2, 3, 4] +... +con.space.test == nil +--- +- true +... +con:reload_schema() +--- +- error: '[string "return con:reload_schema() "]:1: attempt to call method ''reload_schema'' + (a nil value)' +... +con.space.test:select{} +--- +- error: '[string "return con.space.test:select{} "]:1: attempt to index field ''test'' + (a nil value)' +... +box.space.test:drop() +--- +... +box.space.test_old:drop() +--- +... +con:close() +--- +... +file_log = require('fio').open('tarantool.log', {'O_RDONLY', 'O_NONBLOCK'}) +--- +... +file_log:seek(0, 'SEEK_END') ~= 0 +--- +- true +... +--# setopt delimiter ';' +require('fiber').create( + function() + conn = require('net.box').new(box.cfg.listen) + conn.call('no_such_function', {}) + end +); +--- +- status: suspended + name: lua + id: 151 +... +while true do + local line = file_log:read(2048) + if line ~= nil then + if string.match(line, "ER_UNKNOWN") == nil then + return "Success" + else + return "Failure" + end + end + require('fiber').sleep(0.1) +end; +--- +- Success +... +--# setopt delimiter '' +file_log:close() +--- +- true +... diff --git a/test/box/box.net.box.test.lua b/test/box/box.net.box.test.lua index 65309c0321b16a19598fa61598e31da337251d45..a244dd421affa4e13e09f89a24b1be7ab91f2154 100644 --- a/test/box/box.net.box.test.lua +++ b/test/box/box.net.box.test.lua @@ -262,3 +262,52 @@ function gh594() end; --# setopt delimiter '' gh594() + +-- #636: Reload schema on demand +sp = box.schema.create_space('test_old') +sp:create_index('primary') +sp:insert{1, 2, 3} + +con = remote.new(box.cfg.listen) +con:ping() +con.space.test_old:select{} +con.space.test == nil + +sp = box.schema.create_space('test') +sp:create_index('primary') +sp:insert{2, 3, 4} + +con.space.test == nil +con:reload_schema() +con.space.test:select{} + +box.space.test:drop() +box.space.test_old:drop() +con:close() + +file_log = require('fio').open('tarantool.log', {'O_RDONLY', 'O_NONBLOCK'}) +file_log:seek(0, 'SEEK_END') ~= 0 + +--# setopt delimiter ';' + +require('fiber').create( + function() + conn = require('net.box').new(box.cfg.listen) + conn.call('no_such_function', {}) + end +); +while true do + local line = file_log:read(2048) + if line ~= nil then + if string.match(line, "ER_UNKNOWN") == nil then + return "Success" + else + return "Failure" + end + end + require('fiber').sleep(0.1) +end; + +--# setopt delimiter '' + +file_log:close()