From 1203bf90b7ede74ae178da586745aada8eba675c Mon Sep 17 00:00:00 2001 From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Date: Wed, 8 May 2019 19:37:59 +0300 Subject: [PATCH] swim: Lua bindings to manipulate member table Expose methods to add, remove, probe members by uri, uuid. Expose broadcast method to probe multiple members by port. Part of #3234 --- src/lua/swim.lua | 71 +++++++++++++++++ test/swim/swim.result | 171 ++++++++++++++++++++++++++++++++++++++++ test/swim/swim.test.lua | 61 ++++++++++++++ 3 files changed, 303 insertions(+) diff --git a/src/lua/swim.lua b/src/lua/swim.lua index bca98627c5..c828faceb0 100644 --- a/src/lua/swim.lua +++ b/src/lua/swim.lua @@ -272,6 +272,73 @@ local function swim_serialize(s) return s.cfg.index end +-- +-- Ping a member probably located at @a uri. +-- +local function swim_probe_member(s, uri) + local func_name = 'swim:probe_member' + local ptr = swim_check_instance(s, func_name) + uri = swim_check_uri(uri, func_name) + if capi.swim_probe_member(ptr, uri) ~= 0 then + return nil, box.error.last() + end + return true +end + +-- +-- Add a new member to the member table explicitly. +-- +local function swim_add_member(s, cfg) + local func_name = 'swim:add_member' + local ptr = swim_check_instance(s, func_name) + if type(cfg) ~= 'table' then + return error(func_name..': expected table member definition') + end + local uri = swim_check_uri(cfg.uri, func_name) + local uuid = swim_check_uuid(cfg.uuid, func_name) + if capi.swim_add_member(ptr, uri, uuid) ~= 0 then + return nil, box.error.last() + end + return true +end + +-- +-- Remove a member by @a uuid immediately from the local member +-- table. +-- +local function swim_remove_member(s, uuid) + local func_name = 'swim:remove_member' + local ptr = swim_check_instance(s, func_name) + uuid = swim_check_uuid(uuid, func_name) + if capi.swim_remove_member(ptr, uuid) ~= 0 then + return nil, box.error.last() + end + return true +end + +-- +-- Broadcast a ping message on all interfaces with @a port +-- destination. Port can be omitted, then currently bound is used. +-- +local function swim_broadcast(s, port) + local func_name = 'swim:broadcast' + local ptr = swim_check_instance(s, func_name) + if port == nil then + port = -1 + else + if type(port) == 'string' then + port = tonumber(port) + end + if type(port) ~= 'number' then + return error(func_name..': expected number port') + end + end + if capi.swim_broadcast(ptr, port) ~= 0 then + return nil, box.error.last() + end + return true +end + -- -- Normal metatable of a configured SWIM instance. -- @@ -281,6 +348,10 @@ local swim_mt = { quit = swim_quit, size = swim_size, is_configured = swim_is_configured, + probe_member = swim_probe_member, + add_member = swim_add_member, + remove_member = swim_remove_member, + broadcast = swim_broadcast, }, __serialize = swim_serialize } diff --git a/test/swim/swim.result b/test/swim/swim.result index 2e5025da6a..eb23411555 100644 --- a/test/swim/swim.result +++ b/test/swim/swim.result @@ -195,6 +195,177 @@ s.cfg() s:delete() --- ... +-- +-- Basic member table manipulations. +-- +s1 = swim.new({uuid = uuid(1), uri = uri(), heartbeat_rate = 0.01}) +--- +... +s2 = swim.new({uuid = uuid(2), uri = listen_uri, heartbeat_rate = 0.01}) +--- +... +s1.broadcast() +--- +- error: 'builtin/swim.lua:<line>: swim:broadcast: first argument is not a SWIM instance' +... +s1:broadcast('wrong port') +--- +- error: 'swim:broadcast: expected number port' +... +-- Note, broadcast takes a port, not a URI. +s1:broadcast('127.0.0.1:3333') +--- +- error: 'swim:broadcast: expected number port' +... +-- Ok to broadcast on default port. +s1:broadcast() +--- +- true +... +s1:broadcast(listen_port) +--- +- true +... +while s2:size() ~= 2 do fiber.sleep(0.01) end +--- +... +s1:size() +--- +- 2 +... +s2:size() +--- +- 2 +... +s2:delete() +--- +... +s1.remove_member() +--- +- error: 'builtin/swim.lua:<line>: swim:remove_member: first argument is not a SWIM instance' +... +s1:remove_member(100) +--- +- error: 'builtin/swim.lua:<line>: swim:remove_member: expected string UUID' +... +s1:remove_member('1234') +--- +- error: 'builtin/swim.lua:<line>: swim:remove_member: invalid UUID' +... +s1:remove_member(uuid(2)) +--- +- true +... +s1:size() +--- +- 1 +... +s1.add_member() +--- +- error: 'builtin/swim.lua:<line>: swim:add_member: first argument is not a SWIM instance' +... +s1:add_member(100) +--- +- error: 'swim:add_member: expected table member definition' +... +s1:add_member({uri = true}) +--- +- error: 'builtin/swim.lua:<line>: swim:add_member: expected string URI or port number' +... +s1:add_member({uri = listen_uri}) +--- +- null +- 'swim.add_member: URI and UUID are mandatory' +... +s1:add_member({uuid = uuid(2)}) +--- +- null +- 'swim.add_member: URI and UUID are mandatory' +... +s1:add_member({uri = listen_uri, uuid = uuid(2)}) +--- +- true +... +s1:add_member({uri = listen_uri, uuid = uuid(2)}) +--- +- null +- 'swim.add_member: a member with such UUID already exists' +... +s1:size() +--- +- 2 +... +s1:cfg({uuid = uuid(3)}) +--- +- true +... +-- Can't remove self. +s1:remove_member(uuid(3)) +--- +- null +- 'swim.remove_member: can not remove self' +... +-- Not existing. +s1:remove_member(uuid(4)) +--- +- true +... +-- Old self. +s1:remove_member(uuid(1)) +--- +- true +... +s1:delete() +--- +... +s1 = swim.new({uuid = uuid(1), uri = uri()}) +--- +... +s2 = swim.new({uuid = uuid(2), uri = listen_uri}) +--- +... +s1.probe_member() +--- +- error: 'builtin/swim.lua:<line>: swim:probe_member: first argument is not a SWIM instance' +... +s1:probe_member() +--- +- null +- 'swim.probe_member: URI is mandatory' +... +s1:probe_member(true) +--- +- error: 'builtin/swim.lua:<line>: swim:probe_member: expected string URI or port number' +... +-- Not existing URI is ok - nothing happens. +s1:probe_member('127.0.0.1:1') +--- +- true +... +fiber.yield() +--- +... +s1:size() +--- +- 1 +... +s1:probe_member(listen_uri) +--- +- true +... +while s1:size() ~= 2 do fiber.sleep(0.01) end +--- +... +s2:size() +--- +- 2 +... +s1:delete() +--- +... +s2:delete() +--- +... test_run:cmd("clear filter") --- - true diff --git a/test/swim/swim.test.lua b/test/swim/swim.test.lua index 7197831339..d3667376e4 100644 --- a/test/swim/swim.test.lua +++ b/test/swim/swim.test.lua @@ -65,4 +65,65 @@ s.is_configured() s.cfg() s:delete() +-- +-- Basic member table manipulations. +-- +s1 = swim.new({uuid = uuid(1), uri = uri(), heartbeat_rate = 0.01}) +s2 = swim.new({uuid = uuid(2), uri = listen_uri, heartbeat_rate = 0.01}) + +s1.broadcast() +s1:broadcast('wrong port') +-- Note, broadcast takes a port, not a URI. +s1:broadcast('127.0.0.1:3333') +-- Ok to broadcast on default port. +s1:broadcast() + +s1:broadcast(listen_port) +while s2:size() ~= 2 do fiber.sleep(0.01) end +s1:size() +s2:size() + +s2:delete() + +s1.remove_member() +s1:remove_member(100) +s1:remove_member('1234') +s1:remove_member(uuid(2)) +s1:size() + +s1.add_member() +s1:add_member(100) +s1:add_member({uri = true}) +s1:add_member({uri = listen_uri}) +s1:add_member({uuid = uuid(2)}) +s1:add_member({uri = listen_uri, uuid = uuid(2)}) +s1:add_member({uri = listen_uri, uuid = uuid(2)}) +s1:size() + +s1:cfg({uuid = uuid(3)}) +-- Can't remove self. +s1:remove_member(uuid(3)) +-- Not existing. +s1:remove_member(uuid(4)) +-- Old self. +s1:remove_member(uuid(1)) + +s1:delete() + +s1 = swim.new({uuid = uuid(1), uri = uri()}) +s2 = swim.new({uuid = uuid(2), uri = listen_uri}) +s1.probe_member() +s1:probe_member() +s1:probe_member(true) +-- Not existing URI is ok - nothing happens. +s1:probe_member('127.0.0.1:1') +fiber.yield() +s1:size() +s1:probe_member(listen_uri) +while s1:size() ~= 2 do fiber.sleep(0.01) end +s2:size() + +s1:delete() +s2:delete() + test_run:cmd("clear filter") -- GitLab