Fix some bugs and problems in gossip (#3527)
* Allow configuration of debugOutput to be performed * don't send to own IP or update own data * Use same socket to send and receive. Avoid problems in many opened and closed sockets to send * Add callback for REMOVEed hosts * Send broascast messages if seedList is empty * Adapt yeelink to new luacheck rules * Fix building of luac.cross for win to win2019 and VS 2019
This commit is contained in:
parent
27dbe11fcb
commit
193fe3593e
|
@ -58,7 +58,7 @@ jobs:
|
||||||
|
|
||||||
build_luac_cross_win:
|
build_luac_cross_win:
|
||||||
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-2019
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
|
|
@ -28,6 +28,8 @@ uz_zip
|
||||||
|
|
||||||
# ignore VS Code files
|
# ignore VS Code files
|
||||||
.vscode/**
|
.vscode/**
|
||||||
|
# ignore VS files
|
||||||
|
.vs/**
|
||||||
|
|
||||||
# ignore IDEA files
|
# ignore IDEA files
|
||||||
.idea
|
.idea
|
||||||
|
|
|
@ -68,7 +68,7 @@ gossip.setConfig(config)
|
||||||
|
|
||||||
Sets the configuration for gossip. The available options are:
|
Sets the configuration for gossip. The available options are:
|
||||||
|
|
||||||
`seedList` : the list of seeds gossip will start with; this will be updated as new nodes are discovered. Note that it's enough for all nodes to start with the same IP in the seedList, as once they have one seed in common, the data will propagate
|
`seedList` : the list of seeds gossip will start with; this will be updated as new nodes are discovered. Note that it's enough for all nodes to start with the same IP in the seedList, as once they have one seed in common, the data will propagate. If the seedList is empty a broadcast is sent, so this can be used for automatic discovery of nodes.
|
||||||
|
|
||||||
`roundInterval`: interval in milliseconds at which gossip will pick a random node from the seed list and send a `SYN` request
|
`roundInterval`: interval in milliseconds at which gossip will pick a random node from the seed list and send a `SYN` request
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,7 @@ end
|
||||||
|
|
||||||
utils.debug = function(message)
|
utils.debug = function(message)
|
||||||
if gossip.config.debug then
|
if gossip.config.debug then
|
||||||
if gossip.config.debugOutput then
|
|
||||||
gossip.config.debugOutput(message);
|
gossip.config.debugOutput(message);
|
||||||
else
|
|
||||||
print(message);
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -105,15 +101,23 @@ state.start = function()
|
||||||
return;
|
return;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- sending to own IP makes no sense
|
||||||
|
for index, value in ipairs(gossip.config.seedList) do
|
||||||
|
if value == gossip.ip then
|
||||||
|
table.remove(gossip.config.seedList, index)
|
||||||
|
utils.debug('removing own ip from seed list')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
gossip.networkState[gossip.ip] = {};
|
gossip.networkState[gossip.ip] = {};
|
||||||
local localState = gossip.networkState[gossip.ip];
|
local localState = gossip.networkState[gossip.ip];
|
||||||
localState.revision = state.setRev();
|
localState.revision = state.setRev();
|
||||||
localState.heartbeat = tmr.time();
|
localState.heartbeat = tmr.time();
|
||||||
localState.state = constants.nodeState.UP;
|
localState.state = constants.nodeState.UP;
|
||||||
|
|
||||||
gossip.inboundSocket = net.createUDPSocket();
|
gossip.socket = net.createUDPSocket();
|
||||||
gossip.inboundSocket:listen(gossip.config.comPort);
|
gossip.socket:listen(gossip.config.comPort);
|
||||||
gossip.inboundSocket:on('receive', network.receiveData);
|
gossip.socket:on('receive', network.receiveData);
|
||||||
|
|
||||||
gossip.started = true;
|
gossip.started = true;
|
||||||
|
|
||||||
|
@ -128,16 +132,25 @@ end
|
||||||
state.tickNodeState = function(ip)
|
state.tickNodeState = function(ip)
|
||||||
if gossip.networkState[ip] then
|
if gossip.networkState[ip] then
|
||||||
local nodeState = gossip.networkState[ip].state;
|
local nodeState = gossip.networkState[ip].state;
|
||||||
|
local oldNodeState = nodeState;
|
||||||
if nodeState < constants.nodeState.REMOVE then
|
if nodeState < constants.nodeState.REMOVE then
|
||||||
nodeState = nodeState + constants.nodeState.TICK;
|
nodeState = nodeState + constants.nodeState.TICK;
|
||||||
gossip.networkState[ip].state = nodeState;
|
gossip.networkState[ip].state = nodeState;
|
||||||
end
|
end
|
||||||
|
if oldNodeState == constants.nodeState.DOWN then
|
||||||
|
if gossip.updateCallback then gossip.updateCallback(gossip.networkState[ip]); end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Network
|
-- Network
|
||||||
|
network.broadcastIp = "255.255.255.255"
|
||||||
|
|
||||||
network.pushGossip = function(data, ip)
|
network.pushGossip = function(data, ip)
|
||||||
|
if not gossip.started then
|
||||||
|
utils.debug('Gossip not started.');
|
||||||
|
return;
|
||||||
|
end
|
||||||
gossip.networkState[gossip.ip].data = data;
|
gossip.networkState[gossip.ip].data = data;
|
||||||
network.sendSyn(nil, ip);
|
network.sendSyn(nil, ip);
|
||||||
end
|
end
|
||||||
|
@ -145,11 +158,13 @@ end
|
||||||
network.updateNetworkState = function(updateData)
|
network.updateNetworkState = function(updateData)
|
||||||
if gossip.updateCallback then gossip.updateCallback(updateData); end
|
if gossip.updateCallback then gossip.updateCallback(updateData); end
|
||||||
for ip, data in pairs(updateData) do
|
for ip, data in pairs(updateData) do
|
||||||
if not utils.contains(gossip.config.seedList, ip) then
|
if not utils.contains(gossip.config.seedList, ip) and ip ~= network.broadcastIp and ip ~= gossip.ip then
|
||||||
table.insert(gossip.config.seedList, ip);
|
table.insert(gossip.config.seedList, ip);
|
||||||
end
|
end
|
||||||
|
if ip ~= gossip.ip then
|
||||||
gossip.networkState[ip] = data;
|
gossip.networkState[ip] = data;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- luacheck: push no unused
|
-- luacheck: push no unused
|
||||||
|
@ -170,17 +185,16 @@ network.pickRandomNode = function()
|
||||||
return gossip.config.seedList[randomListPick];
|
return gossip.config.seedList[randomListPick];
|
||||||
end
|
end
|
||||||
utils.debug(
|
utils.debug(
|
||||||
'Seedlist is empty. Please provide one or wait for node to be contacted.');
|
'Seedlist is empty. Using broadcast IP '..network.broadcastIp..' to discover.');
|
||||||
return nil;
|
return network.broadcastIp;
|
||||||
end
|
end
|
||||||
|
|
||||||
network.sendData = function(ip, data, sendType)
|
network.sendData = function(ip, data, sendType)
|
||||||
local outboundSocket = net.createUDPSocket();
|
data.type = sendType
|
||||||
data.type = sendType;
|
local dataToSend = sjson.encode(data)
|
||||||
local dataToSend = sjson.encode(data);
|
data.type = nil
|
||||||
data.type = nil;
|
gossip.socket:send(gossip.config.comPort, ip, dataToSend)
|
||||||
outboundSocket:send(gossip.config.comPort, ip, dataToSend);
|
utils.debug("Sent "..#dataToSend.." bytes")
|
||||||
outboundSocket:close();
|
|
||||||
end
|
end
|
||||||
|
|
||||||
network.receiveSyn = function(ip, synData)
|
network.receiveSyn = function(ip, synData)
|
||||||
|
@ -235,7 +249,8 @@ constants.defaultConfig = {
|
||||||
seedList = {},
|
seedList = {},
|
||||||
roundInterval = 15000,
|
roundInterval = 15000,
|
||||||
comPort = 5000,
|
comPort = 5000,
|
||||||
debug = false
|
debug = false,
|
||||||
|
debugOutput = print
|
||||||
};
|
};
|
||||||
|
|
||||||
constants.comparisonFields = {'revision', 'heartbeat', 'state'};
|
constants.comparisonFields = {'revision', 'heartbeat', 'state'};
|
||||||
|
|
|
@ -24,6 +24,7 @@ file.putcontents = dummy
|
||||||
|
|
||||||
local Ip_1 = '192.168.0.1';
|
local Ip_1 = '192.168.0.1';
|
||||||
local Ip_2 = '192.168.0.2';
|
local Ip_2 = '192.168.0.2';
|
||||||
|
local Ip_own = '192.168.0.3';
|
||||||
|
|
||||||
-- test runner
|
-- test runner
|
||||||
|
|
||||||
|
@ -186,20 +187,19 @@ function Test.utils_getMinus()
|
||||||
state = constants.nodeState.SUSPECT;
|
state = constants.nodeState.SUSPECT;
|
||||||
};
|
};
|
||||||
|
|
||||||
--local diff1 = utils.getMinus(data1, data2);
|
local diff1 = utils.getMinus(data1, data2);
|
||||||
local diff2 = utils.getMinus(data2, data1);
|
local diff2 = utils.getMinus(data2, data1);
|
||||||
|
|
||||||
--assert(diff1[Ip_1] ~= nil and diff1[Ip_2] == nil);
|
assert(diff1[Ip_1] ~= nil and diff1[Ip_2] == nil);
|
||||||
assert(diff2[Ip_1] == nil and diff2[Ip_2] ~= nil);
|
assert(diff2[Ip_1] == nil and diff2[Ip_2] ~= nil);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- state
|
-- state
|
||||||
|
|
||||||
function Test.state_setRev()
|
function Test.state_setRev()
|
||||||
gossip.ip = Ip_1;
|
gossip.ip = Ip_own;
|
||||||
gossip.networkState[Ip_1] = {};
|
gossip.networkState[Ip_own] = {};
|
||||||
gossip.networkState[Ip_1].revision = -1;
|
gossip.networkState[Ip_own].revision = -1;
|
||||||
assert(state.setRev() == 0, 'Revision not initialized to 0.');
|
assert(state.setRev() == 0, 'Revision not initialized to 0.');
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -223,6 +223,7 @@ end
|
||||||
-- network
|
-- network
|
||||||
|
|
||||||
function Test.network_updateNetworkState_no_callback()
|
function Test.network_updateNetworkState_no_callback()
|
||||||
|
gossip.ip = Ip_own;
|
||||||
local updateData = {}
|
local updateData = {}
|
||||||
updateData[Ip_1] = {
|
updateData[Ip_1] = {
|
||||||
revision = 1,
|
revision = 1,
|
||||||
|
@ -232,7 +233,12 @@ function Test.network_updateNetworkState_no_callback()
|
||||||
updateData[Ip_2] = {
|
updateData[Ip_2] = {
|
||||||
revision = 1,
|
revision = 1,
|
||||||
heartbeat = 700,
|
heartbeat = 700,
|
||||||
state = constants.nodeState.UP
|
state = constants.nodeState.DOWN
|
||||||
|
};
|
||||||
|
updateData[Ip_own] = {
|
||||||
|
revision = 1,
|
||||||
|
heartbeat = 800,
|
||||||
|
state = constants.nodeState.DOWN
|
||||||
};
|
};
|
||||||
network.updateNetworkState(updateData);
|
network.updateNetworkState(updateData);
|
||||||
-- send duplicate data
|
-- send duplicate data
|
||||||
|
|
|
@ -54,10 +54,10 @@ end)
|
||||||
-- apikey must be -> string <-
|
-- apikey must be -> string <-
|
||||||
-- e.g. xxx.init(00000,00000,"123j12b3jkb12k4b23bv54i2b5b3o4")
|
-- e.g. xxx.init(00000,00000,"123j12b3jkb12k4b23bv54i2b5b3o4")
|
||||||
--========================================
|
--========================================
|
||||||
function M.init(_device, _sensor, _apikey)
|
function M.init(device_, sensor_, apikey_)
|
||||||
device = tostring(_device)
|
device = tostring(device_)
|
||||||
sensor = tostring(_sensor)
|
sensor = tostring(sensor_)
|
||||||
apikey = _apikey
|
apikey = apikey_
|
||||||
if dns == "0.0.0.0" then
|
if dns == "0.0.0.0" then
|
||||||
tmr.create():alarm(5000,tmr.ALARM_AUTO,function ()
|
tmr.create():alarm(5000,tmr.ALARM_AUTO,function ()
|
||||||
if dns == "0.0.0.0" then
|
if dns == "0.0.0.0" then
|
||||||
|
@ -90,9 +90,9 @@ end
|
||||||
--
|
--
|
||||||
--e.g. xxx.update(233.333)
|
--e.g. xxx.update(233.333)
|
||||||
--============================================================
|
--============================================================
|
||||||
function M.update(_datapoint)
|
function M.update(datapoint_)
|
||||||
|
|
||||||
datapoint = tostring(_datapoint)
|
datapoint = tostring(datapoint_)
|
||||||
|
|
||||||
sk:on("connection", function()
|
sk:on("connection", function()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue