introducing checkgauge, code beautifications

This commit is contained in:
Axel Kittenberger 2012-10-05 21:48:06 +02:00
parent 1bf1d13eaa
commit 6a862d6b8f
3 changed files with 722 additions and 520 deletions

View File

@ -28,6 +28,64 @@ end
default.rsync = { }
local rsync = default.rsync
-- uses default collect
--
-- used to ensure there aren't typos in the keys
--
rsync.checkgauge = {
default.checkgauge,
-- unsets default user action handlers
onCreate = false,
onModify = false,
onDelete = false,
onStartup = false,
onMove = false,
delete = true,
exclude = true,
source = true,
target = true,
rsync = {
-- rsync binary
binary = true,
-- rsync shortflags
verbose = true,
quiet = true,
checksum = true,
update = true,
links = true,
copy_links = true,
hard_links = true,
perms = true,
executability = true,
acls = true,
xattrs = true,
owner = true,
group = true,
times = true,
sparse = true,
dry_run = true,
whole_file = true,
one_file_system = true,
prune_empty_dirs = true,
ignore_times = true,
compress = true,
cvs_exclude = true,
protect_args = true,
ipv4 = true,
ipv6 = true,
-- further rsync options
rsh = true,
rsync_path = true,
},
}
--
-- Spawns rsync for a list of events
@ -163,10 +221,19 @@ end
--
rsync.init = function(event)
local config = event.config
local inlet = event.inlet
local config = event.config
local inlet = event.inlet
local excludes = inlet.getExcludes( )
local delete = nil
local delete = nil
local target = config.target
if not target then
if not config.host then
error('Internal fail, Neither target nor host is configured')
end
target = config.host .. ':' .. config.targetdir
end
if config.delete then
delete = { '--delete', '--ignore-errors' }
@ -179,7 +246,7 @@ rsync.init = function(event)
'recursive startup rsync: ',
config.source,
' -> ',
config.target
target
)
spawn(
@ -189,7 +256,7 @@ rsync.init = function(event)
config.rsync._computed,
'-r',
config.source,
config.target
target
)
else
@ -202,7 +269,7 @@ rsync.init = function(event)
'recursive startup rsync: ',
config.source,
' -> ',
config.target,
target,
' excluding\n',
exS
)
@ -216,7 +283,7 @@ rsync.init = function(event)
config.rsync._computed,
'-r',
config.source,
config.target
target
)
end
end
@ -225,19 +292,30 @@ end
--
-- Prepares and checks a syncs configuration on startup.
--
rsync.prepare = function( config )
rsync.prepare = function(
config, -- the configuration
level, -- additional error level for inherited use ( by rsyncssh )
skipTarget -- used by rsyncssh, do not check for target
)
if not config.target then
level = level or 4
--
-- First let default.prepare test the checkgauge
--
default.prepare( config, level + 6 )
if not skipTarget and not config.target then
error(
'default.rsync needs "target" configured',
4
level
)
end
if config.rsyncOps then
error(
'"rsyncOps" is outdated please use the new rsync = { ... } syntax.',
4
level
)
end
@ -246,7 +324,7 @@ rsync.prepare = function( config )
'"rsyncOpts" is outdated in favor of the new rsync = { ... } syntax\n"' +
'for which you provided the _extra attribute as well.\n"' +
'Please remove rsyncOpts from your config.',
4
level
)
end
@ -265,7 +343,7 @@ rsync.prepare = function( config )
'"rsyncBinary is outdated in favor of the new rsync = { ... } syntax\n"'+
'for which you provided the binary attribute as well.\n"' +
"Please remove rsyncBinary from your config.'",
4
level
)
end
@ -283,75 +361,108 @@ rsync.prepare = function( config )
if config.rsync._computed then
error(
'please do not use the internal rsync._computed parameter',
4
level
)
end
-- computes the rsync arguments into one list
local rsync = config.rsync;
rsync._computed = { true }
local computed = rsync._computed
local computedN = 1
local shortFlags = {
verbose = 'v',
quiet = 'q',
checksum = 'c',
update = 'u',
links = 'l',
copy_links = 'L',
hard_links = 'H',
perms = 'p',
executability = 'E',
acls = 'A',
xattrs = 'X',
owner = 'o',
group = 'g',
times = 't',
sparse = 'S',
dry_run = 'n',
whole_file = 'W',
one_file_system = 'x',
prune_empty_dirs = 'm',
ignore_times = 'I',
compress = 'z',
cvs_exclude = 'C',
protect_args = 's',
ipv4 = '4',
ipv6 = '6'
}
local shorts = { '-' }
local shortsN = 2
if config.rsync._extra then
for k, v in ipairs( config.rsync._extra ) do
computed[ k + 1 ] = v
computed[ computedN ] = v
computedN = computedN + 1
end
end
if rsync.links then
shorts[ #shorts + 1 ] = 'l'
for k, flag in pairs( shortFlags ) do
if config.rsync[k] then
shorts[ shortsN ] = flag
shortsN = shortsN + 1
end
end
if rsync.times then
shorts[ #shorts + 1 ] = 't'
if config.rsync.rsh then
computed[ computedN ] = '--rsh=' + config.rsync.rsh
computedN = computedN + 1
end
if rsync.protectArgs then
shorts[ #shorts + 1 ] = 's'
if config.rsync.rsync_path then
computed[ computedN ] = '--rsync-path=' + config.rsync.rsync_path
computedN = computedN + 1
end
if #shorts ~= 1 then
if shortsN ~= 2 then
computed[ 1 ] = table.concat( shorts, '' )
else
computed[ 1 ] = { }
end
-- appends a / to target if not present
if string.sub(config.target, -1) ~= '/' then
if not skipTarget and string.sub(config.target, -1) ~= '/' then
config.target = config.target..'/'
end
end
--
-- rsync uses default collect
--
--
-- By default do deletes.
--
rsync.delete = true
--
-- Rsyncd exitcodes
--
rsync.exitcodes = default.rsyncExitCodes
--
-- Calls rsync with this default options
--
rsync.rsync = {
-- The rsync binary to be called.
binary = '/usr/bin/rsync',
links = true,
times = true,
protectArgs = true
binary = '/usr/bin/rsync',
links = true,
times = true,
protect_args = true
}
--
-- Exit codes for rsync.
--
rsync.exitcodes = default.rsyncExitCodes
--
-- Default delay
--

View File

@ -16,344 +16,340 @@
--
if not default then
error('default not loaded');
error( 'default not loaded' );
end
if not default.rsync then
error( 'default.rsync not loaded' );
end
if default.rsyncssh then
error('default-rsyncssh already loaded');
error( 'default-rsyncssh already loaded' );
end
default.rsyncssh = {
--
-- rsyncssh extends default.rsync
--
local rsyncssh = { default.rsync }
default.rsyncssh = rsyncssh
--
-- Spawns rsync for a list of events
--
action = function(inlet)
--
-- used to ensure there aren't typos in the keys
--
rsyncssh.checkgauge = {
local event, event2 = inlet.getEvent()
local config = inlet.getConfig()
-- unsets the inherited value of from default.rsync
target = false,
onMove = true,
-- makes move local on host
-- if fails deletes the source...
if event.etype == 'Move' then
log('Normal', 'Moving ',event.path,' -> ',event2.path)
spawn(event, '/usr/bin/ssh',
config.host,
'mv',
'\"' .. config.targetdir .. event.path .. '\"',
'\"' .. config.targetdir .. event2.path .. '\"',
'||', 'rm', '-rf',
'\"' .. config.targetdir .. event.path .. '\"')
-- rsyncssh users host and targetdir
host = true,
targetdir = true,
-- ssh settings
ssh = {
binary = true,
port = true,
_extra = true
},
-- xargs settings
xargs = {
binary = true,
delimiter = true,
_extra = true
}
}
--
-- Spawns rsync for a list of events
--
rsyncssh.action = function( inlet )
local event, event2 = inlet.getEvent()
local config = inlet.getConfig()
-- makes move local on target host
-- if the move fails, it deletes the source
if event.etype == 'Move' then
log('Normal', 'Moving ',event.path,' -> ',event2.path)
spawn(
event,
config.ssh.binary,
-- config.ssh._computed, TODO XXX
config.host,
'mv',
'\"' .. config.targetdir .. event.path .. '\"',
'\"' .. config.targetdir .. event2.path .. '\"',
'||', 'rm', '-rf',
'\"' .. config.targetdir .. event.path .. '\"')
return
end
-- uses ssh to delete files on remote host
-- instead of constructing rsync filters
if event.etype == 'Delete' then
if not config.delete then
inlet.discardEvent(event)
return
end
-- uses ssh to delete files on remote host
-- instead of constructing rsync filters
if event.etype == 'Delete' then
if not config.delete then
inlet.discardEvent(event)
return
end
local elist = inlet.getEvents(
function(e)
return e.etype == 'Delete'
end
)
local paths = elist.getPaths(
function(etype, path1, path2)
if path2 then
return config.targetdir..path1, config.targetdir..path2
else
return config.targetdir..path1
end
end
)
for _, v in pairs(paths) do
if string.match(v, '^%s*/+%s*$') then
log('Error', 'refusing to `rm -rf /` the target!')
terminate(-1) -- ERRNO
end
end
log('Normal', 'Deleting list\n', table.concat(paths, '\n'))
local params = {}
if config.port then
params[#params + 1] = 'p'
params[#params + 1] = config.port
end
spawn(
elist,
config.ssh.binary,
'<', table.concat(paths, config.xargs.delimiter),
params,
config.ssh._extra,
config.host,
config.xargs.binary,
config.xargs._extra
)
return
end
-- for everything else spawn a rsync
-- gets all other deletes ready to be
-- executed
local elist = inlet.getEvents(
function(e)
-- TODO use a table
return e.etype ~= 'Move' and
e.etype ~= 'Delete' and
e.etype ~= 'Init' and
e.etype ~= 'Blanket'
function( e )
return e.etype == 'Delete'
end
)
local paths = elist.getPaths()
-- returns the paths of the delete list
local paths = elist.getPaths(
function( etype, path1, path2 )
if path2 then
return config.targetdir..path1, config.targetdir..path2
else
return config.targetdir..path1
end
end
)
-- removes trailing slashes from dirs.
for k, v in ipairs(paths) do
if string.byte(v, -1) == 47 then
paths[k] = string.sub(v, 1, -2)
-- ensures none of the paths is '/'
for _, v in pairs( paths ) do
if string.match(v, '^%s*/+%s*$') then
log('Error', 'refusing to `rm -rf /` the target!')
terminate(-1) -- ERRNO
end
end
local sPaths = table.concat(paths, '\n')
local zPaths = table.concat(paths, '\000')
log('Normal', 'Rsyncing list\n', sPaths)
log(
'Normal',
'Deleting list\n',
table.concat( paths, '\n' )
)
local params = { }
spawn(
elist,
config.rsyncBinary,
'<', zPaths,
config.rsyncOpts,
'--from0',
'--files-from=-',
config.source,
config.host .. ':' .. config.targetdir
config.ssh.binary,
'<', table.concat(paths, config.xargs.delimiter),
params,
-- config.ssh._computed, TODO XXX
config.host,
config.xargs.binary,
config.xargs._extra
)
end,
-----
-- Called when collecting a finished child process
return
end
--
collect = function(agent, exitcode)
-- for everything else a rsync is spawned
--
local elist = inlet.getEvents(
function(e)
-- TODO use a table
return e.etype ~= 'Move' and
e.etype ~= 'Delete' and
e.etype ~= 'Init' and
e.etype ~= 'Blanket'
end
)
local config = agent.config
if not agent.isList and agent.etype == 'Init' then
local rc = config.rsyncExitCodes[exitcode]
if rc == 'ok' then
log('Normal', 'Startup of "',agent.source,'" finished: ', exitcode)
elseif rc == 'again' then
if settings.insist then
log('Normal', 'Retrying startup of "',agent.source,'": ', exitcode)
else
log('Error', 'Temporary or permanent failure on startup of "',
agent.source, '". Terminating since "insist" is not set.');
terminate(-1) -- ERRNO
end
elseif rc == 'die' then
log('Error', 'Failure on startup of "',agent.source,'": ', exitcode)
else
log('Error', 'Unknown exitcode on startup of "', agent.source,': "',exitcode)
rc = 'die'
end
return rc
local paths = elist.getPaths( )
--
-- removes trailing slashes from dirs.
--
for k, v in ipairs( paths ) do
if string.byte(v, -1) == 47 then
paths[k] = string.sub(v, 1, -2)
end
if agent.isList then
end
local rc = config.rsyncExitCodes[exitcode]
local sPaths = table.concat(paths, '\n')
local zPaths = table.concat(paths, '\000')
if rc == 'ok' then
log('Normal', 'Finished (list): ',exitcode)
elseif rc == 'again' then
log('Normal', 'Retrying (list): ',exitcode)
elseif rc == 'die' then
log('Error', 'Failure (list): ', exitcode)
log('Normal', 'Rsyncing list\n', sPaths)
spawn(
elist,
config.rsync.binary,
'<', zPaths,
config.rsync._computed,
'--from0',
'--files-from=-',
config.source,
config.host .. ':' .. config.targetdir
)
end
-----
-- Called when collecting a finished child process
--
rsyncssh.collect = function( agent, exitcode )
local config = agent.config
if not agent.isList and agent.etype == 'Init' then
local rc = config.rsyncExitCodes[exitcode]
if rc == 'ok' then
log('Normal', 'Startup of "',agent.source,'" finished: ', exitcode)
elseif rc == 'again' then
if settings.insist then
log('Normal', 'Retrying startup of "',agent.source,'": ', exitcode)
else
log('Error', 'Unknown exitcode (list): ',exitcode)
rc = 'die'
log('Error', 'Temporary or permanent failure on startup of "',
agent.source, '". Terminating since "insist" is not set.');
terminate(-1) -- ERRNO
end
return rc
elseif rc == 'die' then
log('Error', 'Failure on startup of "',agent.source,'": ', exitcode)
else
local rc = config.sshExitCodes[exitcode]
if rc == 'ok' then
log('Normal', 'Finished ',agent.etype,' ',agent.sourcePath,': ',exitcode)
elseif rc == 'again' then
log('Normal', 'Retrying ',agent.etype,' ',agent.sourcePath,': ',exitcode)
elseif rc == 'die' then
log('Normal', 'Failure ',agent.etype,' ',agent.sourcePath,': ',exitcode)
else
log('Error', 'Unknown exitcode ',agent.etype,' ',agent.sourcePath,': ',exitcode)
rc = 'die'
end
return rc
log('Error', 'Unknown exitcode on startup of "', agent.source,': "',exitcode)
rc = 'die'
end
end,
return rc
--
-- spawns the recursive startup sync
--
init = function(event)
end
local config = event.config
local inlet = event.inlet
local excludes = inlet.getExcludes()
local target = config.host .. ':' .. config.targetdir
local delete = nil
if config.delete then
delete = { '--delete', '--ignore-errors' };
end
if #excludes == 0 then
log('Normal', 'Recursive startup rsync: ',config.source,' -> ',target)
spawn(
event, config.rsyncBinary,
delete,
'-r',
config.rsyncOpts,
config.source,
target
)
if agent.isList then
local rc = config.rsyncExitCodes[exitcode]
if rc == 'ok' then
log('Normal', 'Finished (list): ',exitcode)
elseif rc == 'again' then
log('Normal', 'Retrying (list): ',exitcode)
elseif rc == 'die' then
log('Error', 'Failure (list): ', exitcode)
else
local exS = table.concat(excludes, '\n')
log('Normal', 'Recursive startup rsync: ',config.source,
' -> ',target,' with excludes.')
spawn(
event, config.rsyncBinary,
'<', exS,
'--exclude-from=-',
delete,
'-r',
config.rsyncOpts,
config.source,
target
)
log('Error', 'Unknown exitcode (list): ',exitcode)
rc = 'die'
end
end,
return rc
else
local rc = config.sshExitCodes[exitcode]
--
-- checks the configuration.
--
prepare = function(config)
if not config.host then
error('default.rsyncssh needs "host" configured', 4)
if rc == 'ok' then
log('Normal', 'Finished ',agent.etype,' ',agent.sourcePath,': ',exitcode)
elseif rc == 'again' then
log('Normal', 'Retrying ',agent.etype,' ',agent.sourcePath,': ',exitcode)
elseif rc == 'die' then
log('Normal', 'Failure ',agent.etype,' ',agent.sourcePath,': ',exitcode)
else
log('Error', 'Unknown exitcode ',agent.etype,' ',agent.sourcePath,': ',exitcode)
rc = 'die'
end
if not config.targetdir then
error('default.rsyncssh needs "targetdir" configured', 4)
end
return rc
end
if config.rsyncOps then
error('did you mean rsyncOpts with "t"?', 4)
end
end
-- appends a slash to the targetdir if missing
if string.sub(config.targetdir, -1) ~= '/' then
config.targetdir = config.targetdir .. '/'
end
end,
--
-- checks the configuration.
--
rsyncssh.prepare = function( config )
--
-- the rsync binary called
--
rsyncBinary = '/usr/bin/rsync',
default.rsync.prepare( config, 5, true )
--
-- calls rsync with this default short opts
--
rsyncOpts = '-lts',
if not config.host then
error('default.rsyncssh needs "host" configured', 4)
end
--
-- allow processes
--
maxProcesses = 1,
if not config.targetdir then
error('default.rsyncssh needs "targetdir" configured', 4)
end
--
-- The core should not split move events
--
onMove = true,
if config.rsyncOps then
error('did you mean rsyncOpts with "t"?', 4)
end
--
-- default delay
--
delay = 15,
-- appends a slash to the targetdir if missing
if string.sub(config.targetdir, -1) ~= '/' then
config.targetdir = config.targetdir .. '/'
end
end
--
-- allow processes
--
rsyncssh.maxProcesses = 1
--
-- The core should not split move events
--
rsyncssh.onMove = true
--
-- default delay
--
rsyncssh.delay = 15
--
-- by default do deletes
--
delete = true,
--
-- no default exit codes
--
rsyncssh.exitcodes = false
--
-- rsync exit codes
--
rsyncssh.rsyncExitCodes = default.rsyncExitCodes
--
-- ssh exit codes
--
rsyncssh.sshExitCodes = default.sshExitCodes
--
-- xargs calls configuration
--
-- xargs is used to delete multiple remote files, when ssh access is
-- available this is simpler than to build filters for rsync for this.
--
rsyncssh.xargs = {
--
-- rsync exit codes
--
rsyncExitCodes = default.rsyncExitCodes,
-- the binary called (on target host)
binary = '/usr/bin/xargs',
--
-- ssh exit codes
--
sshExitCodes = default.sshExitCodes,
-- delimiter, uses null by default, you might want to override this for older
-- by for example '\n'
delimiter = '\000',
--
-- xargs calls configuration
--
-- xargs is used to delete multiple remote files, when ssh access is
-- available this is simpler than to build filters for rsync for this.
--
xargs = {
--
-- the binary called (on target host)
binary = '/usr/bin/xargs',
--
-- delimiter, uses null by default, you might want to override this for older
-- by for example '\n'
delimiter = '\000',
--
-- extra parameters
_extra = { '-0', 'rm -rf' }
},
--
-- ssh calls configuration
--
-- ssh is used to move and delete files on the target host
--
ssh = {
--
-- the binary called
binary = '/usr/bin/ssh',
--
-- if set connect to this port
port = nil,
--
-- extra parameters
_extra = { }
}
-- extra parameters
_extra = { '-0', 'rm -rf' }
}
--
-- ssh calls configuration
--
-- ssh is used to move and delete files on the target host
--
rsyncssh.ssh = {
--
-- the binary called
--
binary = '/usr/bin/ssh',
--
-- if set connect to this port
--
port = nil,
--
-- extra parameters
--
_extra = { }
}

View File

@ -9,237 +9,332 @@
--============================================================================
if default then
error('default already loaded')
error( 'default already loaded' )
end
default = {
-----
-- Default action calls user scripts on**** functions.
--
action = function(inlet)
-- in case of moves getEvent returns the origin and dest of the move
local event, event2 = inlet.getEvent()
local config = inlet.getConfig()
local func = config['on'.. event.etype]
if func then
func(event, event2)
end
-- 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 = { }
-----
-- Default collector.
--
-- Called when collecting a finished child process
--
collect = function(agent, exitcode)
--
-- used to ensure there aren't typos in the keys
--
default.checkgauge = {
action = true,
checkgauge = true,
collect = true,
delay = true,
exitcodes = true,
init = true,
maxDelays = true,
maxProcesses = true,
onCreate = true,
onModify = true,
onDelete = true,
onStartup = true,
onMove = true,
prepare = true,
rsyncExitCodes = true, -- TODO
sshExitCodes = true -- TODO
}
local config = agent.config
local rc
--
-- On default action the user's on*** scripts are called.
--
default.action = function( inlet )
if config.exitcodes then
rc = config.exitcodes[exitcode]
elseif exitcode == 0 then
rc = 'ok'
else
rc = 'die'
end
-- in case of moves getEvent returns the origin and dest of the move
local event, event2 = inlet.getEvent( )
local config = inlet.getConfig( )
-- 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
if settings.insist then
log(
'Normal',
'Retrying startup of "',
agent.source,
'": ',
exitcode
)
local func = config[ 'on'.. event.etype ]
return 'again'
else
log(
'Error',
'Temporary or permanent failure on startup of "',
agent.source,
'". Terminating since "insist" is not set.'
)
if func then
func( event, event2 )
end
terminate( -1 )
end
elseif rc == 'die' then
-- 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
if settings.insist then
log(
'Normal',
'Retrying startup of "',
agent.source,
'": ',
exitcode
)
return 'again'
else
log(
'Error',
'Failure on startup of "',
'Temporary or permanent failure on startup of "',
agent.source,
'".'
'". Terminating since "insist" is not set.'
)
terminate( -1 )
else
log(
'Error',
'Unknown exitcode "',
exitcode,
'" on startup of "',
agent.source,
'".'
)
return 'die'
end
end
elseif rc == 'die' then
log(
'Error',
'Failure on startup of "',
agent.source,
'".'
)
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'
)
rc = 'die'
end
terminate( -1 )
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'
end
log(
'Error',
'Unknown exitcode "',
exitcode,
'" on startup of "',
agent.source,
'".'
)
return 'die'
end
end
return rc
end,
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'
)
-----
-- called on (re)initialization of Lsyncd.
--
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".
rc = 'die'
end
if event.status == 'wait' then
-- user script did not spawn anything
-- thus the blanket event is deleted again.
inlet.discardEvent(event)
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'
end
end,
end
return rc
end
--
-- 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 maximum number of processes Lsyncd will
-- simultanously spawn for this sync.
--
default.maxProcesses = 1
--
-- 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
---
-- a default configuration using /bin/cp|rm|mv.
-- TODO huh?
--
default.direct = default_direct
--
-- Exitcodes of rsync and what to do.
-- TODO move to rsync
--
default.rsyncExitCodes = {
-----
-- The maximum number of processes Lsyncd will spawn simultanously for
-- one sync.
--
maxProcesses = 1,
-----
-- Try not to have more than these delays.
-- not too large, since total calculation for stacking
-- events is n*log(n) or so..
-- if another config provides the same table
-- this will not be inherited (merged) into that one
--
maxDelays = 1000,
-----
-- a default configuration using /bin/cp|rm|mv.
-- if it does not, integer keys are to be copied
-- verbatim
--
direct = default_direct,
_merge = false,
_verbatim = true,
------
-- Exitcodes of rsync and what to do.
--
rsyncExitCodes = {
[ 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',
--
-- if another config provides the same table
-- this will not be inherited (merged) into that one
--
-- if it does not, integer keys are to be copied
-- verbatim
--
_merge = false,
_verbatim = true,
-- 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',
[ 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',
},
[ 25 ] = 'die',
[ 30 ] = 'again',
[ 35 ] = 'again',
-----
-- Exitcodes of ssh and what to do.
--
sshExitCodes = {
--
-- if another config provides the same table
-- this will not be inherited (merged) into that one
--
-- if it does not, integer keys are to be copied
-- verbatim
--
_merge = false,
_verbatim = true,
[ 0 ] = 'ok',
[ 255 ] = 'again',
},
-----
-- Minimum seconds between two writes of a status file.
--
statusInterval = 10,
[ 255 ] = 'again',
}
--
-- Exitcodes of ssh and what to do.
--
default.sshExitCodes = {
--
-- if another config provides the same table
-- this will not be inherited (merged) into that one
--
-- if it does not, integer keys are to be copied
-- verbatim
--
_merge = false,
_verbatim = true,
[ 0 ] = 'ok',
[ 255 ] = 'again',
}
--
-- 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,
level
)
for k, v in pairs( config ) do
if not gauge[k] then
error(
'Parameter "'
.. 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 "'
.. k
.. '" must be a table.',
level
)
end
check( config[ k ], gauge[ k ], level + 1 )
end
end
end
default.prepare = function( config, level )
local gauge = config.checkgauge
if not gauge then
return
end
check( config, gauge, level or 2 )
end