2012-02-15 19:00:28 +00:00
|
|
|
--============================================================================
|
|
|
|
-- default.lua Live (Mirror) Syncing Demon
|
|
|
|
--
|
|
|
|
-- The default table for the user to access.
|
|
|
|
-- This default layer 1 functions provide the higher layer functionality.
|
|
|
|
--
|
|
|
|
-- License: GPLv2 (see COPYING) or any later version
|
|
|
|
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
|
|
|
--============================================================================
|
|
|
|
|
2012-10-03 16:34:09 +00:00
|
|
|
if default then
|
2012-10-05 19:48:06 +00:00
|
|
|
error( 'default already loaded' )
|
2012-10-03 16:34:09 +00:00
|
|
|
end
|
2012-02-15 19:00:28 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
default = { }
|
2012-02-15 19:00:28 +00:00
|
|
|
|
|
|
|
|
2012-10-06 11:43:55 +00:00
|
|
|
--
|
|
|
|
-- Only this items are inherited from the default
|
|
|
|
-- table
|
|
|
|
--
|
|
|
|
default._merge = {
|
|
|
|
action = true,
|
|
|
|
checkgauge = true,
|
|
|
|
collect = true,
|
|
|
|
delay = true,
|
|
|
|
init = true,
|
|
|
|
maxDelays = true,
|
|
|
|
maxProcesses = true,
|
|
|
|
prepare = true,
|
|
|
|
}
|
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
--
|
|
|
|
-- used to ensure there aren't typos in the keys
|
|
|
|
--
|
|
|
|
default.checkgauge = {
|
2013-05-14 21:13:09 +00:00
|
|
|
action = true,
|
|
|
|
checkgauge = true,
|
|
|
|
collect = true,
|
|
|
|
delay = true,
|
|
|
|
exitcodes = true,
|
|
|
|
init = true,
|
|
|
|
maxDelays = true,
|
|
|
|
maxProcesses = true,
|
|
|
|
onAttrib = true,
|
|
|
|
onCreate = true,
|
|
|
|
onModify = true,
|
|
|
|
onDelete = true,
|
|
|
|
onStartup = true,
|
|
|
|
onMove = true,
|
|
|
|
prepare = true,
|
|
|
|
source = true,
|
|
|
|
target = true,
|
2012-10-05 19:48:06 +00:00
|
|
|
}
|
2012-10-05 07:41:46 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
--
|
|
|
|
-- On default action the user's on*** scripts are called.
|
|
|
|
--
|
|
|
|
default.action = function( inlet )
|
2012-10-05 07:41:46 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
-- in case of moves getEvent returns the origin and dest of the move
|
|
|
|
local event, event2 = inlet.getEvent( )
|
|
|
|
local config = inlet.getConfig( )
|
2012-02-15 19:00:28 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
local func = config[ 'on'.. event.etype ]
|
2012-10-05 07:41:46 +00:00
|
|
|
|
2012-10-10 08:07:13 +00:00
|
|
|
if type( func ) == 'function' then
|
2012-10-05 19:48:06 +00:00
|
|
|
func( event, event2 )
|
|
|
|
end
|
2012-02-15 19:00:28 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
-- if function didnt change the wait status its not interested
|
|
|
|
-- in this event -> drop it.
|
|
|
|
if event.status == 'wait' then
|
|
|
|
inlet.discardEvent( event )
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Default collector.
|
|
|
|
--
|
|
|
|
-- Called when collecting a finished child process
|
|
|
|
--
|
|
|
|
default.collect = function( agent, exitcode )
|
|
|
|
|
|
|
|
local config = agent.config
|
|
|
|
local rc
|
|
|
|
|
|
|
|
if config.exitcodes then
|
|
|
|
rc = config.exitcodes[exitcode]
|
|
|
|
elseif exitcode == 0 then
|
|
|
|
rc = 'ok'
|
|
|
|
else
|
|
|
|
rc = 'die'
|
|
|
|
end
|
|
|
|
|
|
|
|
-- TODO synchronize with similar code before
|
|
|
|
if not agent.isList and agent.etype == 'Init' then
|
|
|
|
if rc == 'ok' then
|
|
|
|
log('Normal', 'Startup of "',agent.source,'" finished.')
|
|
|
|
return 'ok'
|
|
|
|
elseif rc == 'again' then
|
2012-11-09 19:15:42 +00:00
|
|
|
if settings('insist') then
|
2012-10-05 07:41:46 +00:00
|
|
|
log(
|
|
|
|
'Normal',
|
2012-10-05 19:48:06 +00:00
|
|
|
'Retrying startup of "',
|
|
|
|
agent.source,
|
|
|
|
'": ',
|
2012-10-05 07:41:46 +00:00
|
|
|
exitcode
|
|
|
|
)
|
2012-10-05 19:48:06 +00:00
|
|
|
|
|
|
|
return 'again'
|
2012-02-15 19:00:28 +00:00
|
|
|
else
|
2012-10-05 07:41:46 +00:00
|
|
|
log(
|
|
|
|
'Error',
|
2012-10-05 19:48:06 +00:00
|
|
|
'Temporary or permanent failure on startup of "',
|
|
|
|
agent.source,
|
|
|
|
'". Terminating since "insist" is not set.'
|
2012-10-05 07:41:46 +00:00
|
|
|
)
|
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
terminate( -1 )
|
2012-02-15 19:00:28 +00:00
|
|
|
end
|
2012-10-05 19:48:06 +00:00
|
|
|
elseif rc == 'die' then
|
|
|
|
log(
|
|
|
|
'Error',
|
|
|
|
'Failure on startup of "',
|
|
|
|
agent.source,
|
|
|
|
'".'
|
|
|
|
)
|
|
|
|
|
|
|
|
terminate( -1 )
|
2012-02-15 19:00:28 +00:00
|
|
|
else
|
2012-10-05 19:48:06 +00:00
|
|
|
log(
|
|
|
|
'Error',
|
|
|
|
'Unknown exitcode "',
|
|
|
|
exitcode,
|
|
|
|
'" on startup of "',
|
|
|
|
agent.source,
|
|
|
|
'".'
|
|
|
|
)
|
|
|
|
return 'die'
|
2012-02-15 19:00:28 +00:00
|
|
|
end
|
2012-10-05 19:48:06 +00:00
|
|
|
end
|
2012-09-07 16:00:52 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
if agent.isList then
|
|
|
|
if rc == 'ok' then
|
|
|
|
log(
|
|
|
|
'Normal',
|
|
|
|
'Finished a list after exitcode: ',
|
|
|
|
exitcode
|
|
|
|
)
|
|
|
|
elseif rc == 'again' then
|
|
|
|
log(
|
|
|
|
'Normal',
|
|
|
|
'Retrying a list after exitcode = ',
|
|
|
|
exitcode
|
|
|
|
)
|
|
|
|
elseif rc == 'die' then
|
|
|
|
log(
|
|
|
|
'Error',
|
|
|
|
'Failure with a list width exitcode = ',
|
|
|
|
exitcode
|
|
|
|
)
|
|
|
|
else
|
|
|
|
log(
|
|
|
|
'Error',
|
|
|
|
'Unknown exitcode "',exitcode,'" with a list'
|
|
|
|
)
|
2012-02-15 19:00:28 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
rc = 'die'
|
2012-02-15 19:00:28 +00:00
|
|
|
end
|
2012-10-05 19:48:06 +00:00
|
|
|
else
|
|
|
|
if rc == 'ok' then
|
|
|
|
log('Normal', 'Retrying ',agent.etype,' on ',agent.sourcePath,' = ',exitcode)
|
|
|
|
elseif rc == 'again' then
|
|
|
|
log('Normal', 'Finished ',agent.etype,' on ',agent.sourcePath,' = ',exitcode)
|
|
|
|
elseif rc == 'die' then
|
|
|
|
log('Error', 'Failure with ',agent.etype,' on ',agent.sourcePath,' = ',exitcode)
|
|
|
|
else
|
|
|
|
log('Normal', 'Unknown exitcode "',exitcode,'" with ', agent.etype,
|
|
|
|
' on ',agent.sourcePath,' = ',exitcode)
|
|
|
|
rc = 'die'
|
2012-02-15 19:00:28 +00:00
|
|
|
end
|
2012-10-05 19:48:06 +00:00
|
|
|
end
|
2012-02-15 19:00:28 +00:00
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
return rc
|
|
|
|
end
|
2012-02-15 19:00:28 +00:00
|
|
|
|
|
|
|
|
2012-10-05 19:48:06 +00:00
|
|
|
--
|
|
|
|
-- Called on the Init event sent
|
|
|
|
-- on (re)initialization of Lsyncd for every sync
|
|
|
|
--
|
|
|
|
default.init = function(event)
|
|
|
|
local config = event.config
|
|
|
|
local inlet = event.inlet
|
|
|
|
|
|
|
|
-- user functions
|
|
|
|
-- calls a startup if given by user script.
|
|
|
|
if type(config.onStartup) == 'function' then
|
|
|
|
local startup = config.onStartup(event)
|
|
|
|
-- TODO honor some return codes of startup like "warmstart".
|
|
|
|
end
|
|
|
|
|
|
|
|
if event.status == 'wait' then
|
|
|
|
-- user script did not spawn anything
|
|
|
|
-- thus the blanket event is deleted again.
|
|
|
|
inlet.discardEvent(event)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- The collapsor tries not to have more than these delays.
|
|
|
|
-- So it dealy stack does not grow too large,
|
|
|
|
-- since calculation for stacking events is n*log(n) (or so)
|
|
|
|
--
|
|
|
|
default.maxDelays = 1000
|
|
|
|
|
|
|
|
|
|
|
|
--
|
2012-10-06 11:43:55 +00:00
|
|
|
-- The maximum number of processes Lsyncd will
|
|
|
|
-- simultanously spawn for this sync.
|
|
|
|
--
|
|
|
|
default.maxProcesses = 1
|
2012-10-05 19:48:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Exitcodes of rsync and what to do.
|
|
|
|
-- TODO move to rsync
|
|
|
|
--
|
|
|
|
default.rsyncExitCodes = {
|
|
|
|
|
|
|
|
--
|
|
|
|
-- if another config provides the same table
|
|
|
|
-- this will not be inherited (merged) into that one
|
2012-02-15 19:00:28 +00:00
|
|
|
--
|
2012-10-05 19:48:06 +00:00
|
|
|
-- if it does not, integer keys are to be copied
|
|
|
|
-- verbatim
|
|
|
|
--
|
|
|
|
_merge = false,
|
|
|
|
_verbatim = true,
|
|
|
|
|
|
|
|
[ 0 ] = 'ok',
|
|
|
|
[ 1 ] = 'die',
|
|
|
|
[ 2 ] = 'die',
|
|
|
|
[ 3 ] = 'again',
|
|
|
|
[ 4 ] = 'die',
|
|
|
|
[ 5 ] = 'again',
|
|
|
|
[ 6 ] = 'again',
|
|
|
|
[ 10 ] = 'again',
|
|
|
|
[ 11 ] = 'again',
|
|
|
|
[ 12 ] = 'again',
|
|
|
|
[ 14 ] = 'again',
|
|
|
|
[ 20 ] = 'again',
|
|
|
|
[ 21 ] = 'again',
|
|
|
|
[ 22 ] = 'again',
|
|
|
|
|
|
|
|
-- partial transfers are ok, since Lsyncd has registered the event that
|
|
|
|
-- caused the transfer to be partial and will recall rsync.
|
|
|
|
[ 23 ] = 'ok',
|
|
|
|
[ 24 ] = 'ok',
|
|
|
|
|
|
|
|
[ 25 ] = 'die',
|
|
|
|
[ 30 ] = 'again',
|
|
|
|
[ 35 ] = 'again',
|
|
|
|
|
|
|
|
[ 255 ] = 'again',
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Exitcodes of ssh and what to do.
|
|
|
|
--
|
|
|
|
default.sshExitCodes = {
|
2012-02-15 19:00:28 +00:00
|
|
|
|
|
|
|
--
|
2012-10-05 19:48:06 +00:00
|
|
|
-- if another config provides the same table
|
|
|
|
-- this will not be inherited (merged) into that one
|
2012-02-15 19:00:28 +00:00
|
|
|
--
|
2012-10-05 19:48:06 +00:00
|
|
|
-- if it does not, integer keys are to be copied
|
|
|
|
-- verbatim
|
2012-02-15 19:00:28 +00:00
|
|
|
--
|
2012-10-05 19:48:06 +00:00
|
|
|
_merge = false,
|
|
|
|
_verbatim = true,
|
|
|
|
|
|
|
|
[ 0 ] = 'ok',
|
|
|
|
[ 255 ] = 'again',
|
2012-02-15 19:00:28 +00:00
|
|
|
}
|
2012-10-05 19:48:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- Minimum seconds between two writes of a status file.
|
|
|
|
--
|
|
|
|
default.statusInterval = 10
|
|
|
|
|
|
|
|
|
|
|
|
--
|
|
|
|
-- checks all keys to be in the checkgauge
|
|
|
|
--
|
|
|
|
|
|
|
|
local function check(
|
|
|
|
config,
|
|
|
|
gauge,
|
2012-10-06 11:43:55 +00:00
|
|
|
subtable,
|
2012-10-05 19:48:06 +00:00
|
|
|
level
|
|
|
|
)
|
|
|
|
for k, v in pairs( config ) do
|
|
|
|
|
|
|
|
if not gauge[k] then
|
|
|
|
error(
|
|
|
|
'Parameter "'
|
2012-10-06 11:43:55 +00:00
|
|
|
.. subtable
|
2012-10-05 19:48:06 +00:00
|
|
|
.. k
|
|
|
|
.. '" unknown.'
|
|
|
|
.. ' (if this is not a typo add it to checkgauge)',
|
|
|
|
level
|
|
|
|
);
|
|
|
|
end
|
|
|
|
|
|
|
|
if type( gauge [ k ] ) == 'table' then
|
|
|
|
|
|
|
|
if type( v ) ~= 'table' then
|
|
|
|
|
|
|
|
error(
|
|
|
|
'Parameter "'
|
2012-10-06 11:43:55 +00:00
|
|
|
.. subtable
|
2012-10-05 19:48:06 +00:00
|
|
|
.. k
|
|
|
|
.. '" must be a table.',
|
|
|
|
level
|
|
|
|
)
|
|
|
|
|
|
|
|
end
|
|
|
|
|
2012-10-06 11:43:55 +00:00
|
|
|
check(
|
|
|
|
config[ k ],
|
|
|
|
gauge[ k ],
|
|
|
|
subtable .. k .. '.',
|
|
|
|
level + 1
|
|
|
|
)
|
2012-10-05 19:48:06 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
default.prepare = function( config, level )
|
|
|
|
|
|
|
|
local gauge = config.checkgauge
|
|
|
|
|
|
|
|
if not gauge then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2012-10-06 12:22:08 +00:00
|
|
|
check( config, gauge, '', level + 1 )
|
2012-10-05 19:48:06 +00:00
|
|
|
end
|
|
|
|
|