mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-11-11 07:40:55 +00:00
rewriting inheritance logic. splitting default and proto
This commit is contained in:
parent
6f1f873c29
commit
ade3d30c58
300
default/proto.lua
Normal file
300
default/proto.lua
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
--============================================================================
|
||||||
|
-- proto.lua Live (Mirror) Syncing Demon
|
||||||
|
--
|
||||||
|
-- The default behavior of all syncs.
|
||||||
|
--
|
||||||
|
-- This default layer 1 functions provide the higher layer functionality.
|
||||||
|
--
|
||||||
|
-- License: GPLv2 (see COPYING) or any later version
|
||||||
|
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||||
|
--============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
if not default then error( 'default not loaded' ) end
|
||||||
|
|
||||||
|
if default.proto then error( 'default-proto already loaded' ) end
|
||||||
|
|
||||||
|
proto = { }
|
||||||
|
|
||||||
|
default.proto = proto
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- used to ensure there aren't typos in the keys
|
||||||
|
--
|
||||||
|
proto.checkgauge =
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- On default action the user's on*** scripts are called.
|
||||||
|
--
|
||||||
|
proto.action = function
|
||||||
|
(
|
||||||
|
inlet -- the inlet of the active sync.
|
||||||
|
)
|
||||||
|
-- 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 type( func ) == 'function'
|
||||||
|
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 collector.
|
||||||
|
--
|
||||||
|
-- Called when collecting a finished child process
|
||||||
|
--
|
||||||
|
proto.collect = function
|
||||||
|
(
|
||||||
|
agent, -- event or event list being collected
|
||||||
|
exitcode -- the exitcode of the spawned process
|
||||||
|
)
|
||||||
|
local config = agent.config
|
||||||
|
|
||||||
|
local rc
|
||||||
|
|
||||||
|
if agent.syncStopped
|
||||||
|
then
|
||||||
|
log( 'Normal', 'Sync stopped, ignoring exitcode of finished child' )
|
||||||
|
return 'ok'
|
||||||
|
end
|
||||||
|
|
||||||
|
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, ' -> ',agent.target,' finished.'
|
||||||
|
)
|
||||||
|
|
||||||
|
return 'ok'
|
||||||
|
elseif rc == 'again'
|
||||||
|
then
|
||||||
|
if settings( 'insist' )
|
||||||
|
then
|
||||||
|
log(
|
||||||
|
'Normal',
|
||||||
|
'Retrying startup of ',
|
||||||
|
agent.source, ' -> ', agent.target,
|
||||||
|
': ', exitcode
|
||||||
|
)
|
||||||
|
|
||||||
|
return 'again'
|
||||||
|
end
|
||||||
|
elseif rc == 'die'
|
||||||
|
then
|
||||||
|
log(
|
||||||
|
'Error',
|
||||||
|
'Failure on startup of ',
|
||||||
|
agent.source, ' -> ', agent.target
|
||||||
|
)
|
||||||
|
|
||||||
|
terminate( -1 )
|
||||||
|
else
|
||||||
|
log(
|
||||||
|
'Error',
|
||||||
|
'Unknown exitcode "', exitcode,
|
||||||
|
'" on startup of ',
|
||||||
|
agent.source, ' -> ', agent.target
|
||||||
|
)
|
||||||
|
return 'die'
|
||||||
|
end
|
||||||
|
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 with exitcode = ', exitcode )
|
||||||
|
else
|
||||||
|
log( 'Error', 'Unknown exitcode "', exitcode, '" with a list' )
|
||||||
|
|
||||||
|
rc = 'die'
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if rc == 'ok'
|
||||||
|
then
|
||||||
|
log(
|
||||||
|
'Normal',
|
||||||
|
'Finished ', agent.etype,
|
||||||
|
' on ', agent.sourcePath, ' = ', exitcode
|
||||||
|
)
|
||||||
|
elseif rc == 'again'
|
||||||
|
then
|
||||||
|
log(
|
||||||
|
'Normal',
|
||||||
|
'Retrying ', 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
|
||||||
|
|
||||||
|
return rc
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Called on the Init event sent
|
||||||
|
-- on (re)initialization of Lsyncd for every sync
|
||||||
|
--
|
||||||
|
proto.init = function
|
||||||
|
(
|
||||||
|
event -- the precreated init 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
|
||||||
|
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 the delay queue does not grow too large
|
||||||
|
-- since calculation for stacking events is n*log( n ) (or so)
|
||||||
|
--
|
||||||
|
proto.maxDelays = 1000
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- The maximum number of processes Lsyncd will
|
||||||
|
-- simultanously spawn for this sync.
|
||||||
|
--
|
||||||
|
proto.maxProcesses = 1
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Checks all keys to be in the checkgauge.
|
||||||
|
--
|
||||||
|
local function check
|
||||||
|
(
|
||||||
|
config,
|
||||||
|
gauge,
|
||||||
|
subtable,
|
||||||
|
level
|
||||||
|
)
|
||||||
|
for k, v in pairs( config )
|
||||||
|
do
|
||||||
|
if not gauge[ k ]
|
||||||
|
then
|
||||||
|
error(
|
||||||
|
'Parameter "' .. subtable .. 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 "' .. subtable .. k .. '" must be a table.',
|
||||||
|
level
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
check(
|
||||||
|
config[ k ],
|
||||||
|
gauge[ k ],
|
||||||
|
subtable .. k .. '.',
|
||||||
|
level + 1
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
proto.prepare = function
|
||||||
|
(
|
||||||
|
config, -- the config to prepare for
|
||||||
|
level -- current callback level for error reporting
|
||||||
|
)
|
||||||
|
|
||||||
|
local gauge = config.checkgauge
|
||||||
|
|
||||||
|
if not gauge then return end
|
||||||
|
|
||||||
|
check( config, gauge, '', level + 1 )
|
||||||
|
end
|
||||||
|
|
@ -31,7 +31,6 @@ default.rsync = rsync
|
|||||||
-- used to ensure there aren't typos in the keys
|
-- used to ensure there aren't typos in the keys
|
||||||
--
|
--
|
||||||
rsync.checkgauge = {
|
rsync.checkgauge = {
|
||||||
|
|
||||||
-- unsets default user action handlers
|
-- unsets default user action handlers
|
||||||
onCreate = false,
|
onCreate = false,
|
||||||
onModify = false,
|
onModify = false,
|
||||||
@ -628,14 +627,9 @@ rsync.delete = true
|
|||||||
--
|
--
|
||||||
rsync.exitcodes =
|
rsync.exitcodes =
|
||||||
{
|
{
|
||||||
--
|
|
||||||
-- if another config provides the same table
|
-- if another config provides the same table
|
||||||
-- this will not be inherited (merged) into that one
|
-- this will not be merged into that one
|
||||||
--
|
_merge = false,
|
||||||
-- if it does not, integer keys are to be copied
|
|
||||||
-- verbatim
|
|
||||||
--
|
|
||||||
_verbatim = true,
|
|
||||||
|
|
||||||
[ 0 ] = 'ok',
|
[ 0 ] = 'ok',
|
||||||
[ 1 ] = 'die',
|
[ 1 ] = 'die',
|
||||||
|
@ -41,6 +41,8 @@ default.rsyncssh = rsyncssh
|
|||||||
-- used to ensure there aren't typos in the keys
|
-- used to ensure there aren't typos in the keys
|
||||||
--
|
--
|
||||||
rsyncssh.checkgauge = {
|
rsyncssh.checkgauge = {
|
||||||
|
-- inherits the rsync checkgauge
|
||||||
|
default.rsync.checkgauge,
|
||||||
|
|
||||||
-- unsets the inherited value of from default.rsync
|
-- unsets the inherited value of from default.rsync
|
||||||
target = false,
|
target = false,
|
||||||
@ -577,13 +579,8 @@ rsyncssh.sshExitCodes =
|
|||||||
{
|
{
|
||||||
--
|
--
|
||||||
-- if another config provides the same table
|
-- if another config provides the same table
|
||||||
-- this will not be inherited (merged) into that one
|
-- this will not be merged into that one
|
||||||
--
|
|
||||||
-- if it does not, integer keys are to be copied
|
|
||||||
-- verbatim
|
|
||||||
--
|
|
||||||
_merge = false,
|
_merge = false,
|
||||||
_verbatim = true,
|
|
||||||
|
|
||||||
[ 0 ] = 'ok',
|
[ 0 ] = 'ok',
|
||||||
[ 255 ] = 'again',
|
[ 255 ] = 'again',
|
||||||
|
@ -80,11 +80,40 @@ local function get
|
|||||||
return syncList[ i ]
|
return syncList[ i ]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local inherit
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Helper function for inherit
|
-- Inherits the contents of all tables with array keys
|
||||||
-- defined below
|
-- Returns the table with flattened inhertance,
|
||||||
|
-- also returns array size
|
||||||
--
|
--
|
||||||
local inheritKV
|
--
|
||||||
|
local function flattenInheritance
|
||||||
|
(
|
||||||
|
t
|
||||||
|
)
|
||||||
|
local tf = { }
|
||||||
|
|
||||||
|
inherit( tf, t )
|
||||||
|
|
||||||
|
for k, v in ipairs( t )
|
||||||
|
do
|
||||||
|
-- numbers as key and table as value
|
||||||
|
-- means recursive inherit
|
||||||
|
if type( v ) == 'table'
|
||||||
|
then
|
||||||
|
local vv = flattenInheritance( v )
|
||||||
|
inherit( tf, vv )
|
||||||
|
else
|
||||||
|
if tf[ k ] == nil then tf[ k ] = v end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tf
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Recursevly inherits a source table to a destionation table
|
-- Recursevly inherits a source table to a destionation table
|
||||||
@ -93,75 +122,52 @@ local inheritKV
|
|||||||
-- All entries with integer keys are inherited as additional
|
-- All entries with integer keys are inherited as additional
|
||||||
-- sources for non-verbatim tables
|
-- sources for non-verbatim tables
|
||||||
--
|
--
|
||||||
local function inherit
|
inherit = function
|
||||||
(
|
(
|
||||||
cd, -- table copy destination
|
cd, -- table copy destination
|
||||||
cs, -- table copy source
|
cs -- table copy source
|
||||||
verbatim -- forced verbatim ( for e.g. 'exitcodes' )
|
|
||||||
)
|
)
|
||||||
-- First copies all entries with non-integer keys.
|
local imax = 0
|
||||||
--
|
|
||||||
-- Tables are merged; already present keys are not
|
for k, _ in ipairs( cs ) do imax = k end
|
||||||
-- overwritten
|
|
||||||
--
|
|
||||||
-- For verbatim tables integer keys are treated like
|
|
||||||
-- non-integer keys
|
|
||||||
for k, v in pairs( cs )
|
for k, v in pairs( cs )
|
||||||
do
|
do
|
||||||
if type( k ) ~= 'number'
|
if type( k ) == 'number'
|
||||||
or verbatim
|
|
||||||
or cs._verbatim == true
|
|
||||||
then
|
then
|
||||||
inheritKV( cd, k, v )
|
if( k < 1 or k > imax or math.floor( k ) ~= k )
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- recursevely inherits all integer keyed tables
|
|
||||||
-- ( for non-verbatim tables )
|
|
||||||
if cs._verbatim ~= true
|
|
||||||
then
|
then
|
||||||
for k, v in ipairs( cs )
|
-- not an array integer
|
||||||
do
|
|
||||||
if type( v ) == 'table'
|
if type( v ) == 'table'
|
||||||
then
|
then
|
||||||
inherit( cd, v )
|
error( 'non sequence numeric key used as inheritance', 2 )
|
||||||
|
end
|
||||||
|
|
||||||
|
if cd[ k ] == nil then cd[ k ] = v end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
cd[ #cd + 1 ] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Helper to inherit. Inherits one key.
|
|
||||||
--
|
|
||||||
inheritKV =
|
|
||||||
function(
|
|
||||||
cd, -- table copy destination
|
|
||||||
k, -- key
|
|
||||||
v -- value
|
|
||||||
)
|
|
||||||
|
|
||||||
-- don't merge inheritance controls
|
|
||||||
if k == '_verbatim' then return end
|
|
||||||
|
|
||||||
local dtype = type( cd [ k ] )
|
|
||||||
|
|
||||||
if type( v ) == 'table'
|
if type( v ) == 'table'
|
||||||
then
|
then
|
||||||
if dtype == 'nil'
|
v = flattenInheritance( v )
|
||||||
then
|
|
||||||
cd[ k ] = { }
|
|
||||||
inherit( cd[ k ], v, k == 'exitcodes' )
|
|
||||||
elseif dtype == 'table'
|
|
||||||
then
|
|
||||||
inherit( cd[ k ], v, k == 'exitcodes' )
|
|
||||||
end
|
end
|
||||||
elseif dtype == 'nil'
|
|
||||||
|
local dv = cd[ k ]
|
||||||
|
|
||||||
|
if dv == nil
|
||||||
then
|
then
|
||||||
cd[ k ] = v
|
cd[ k ] = v
|
||||||
|
elseif type( dv ) == 'table'
|
||||||
|
and type( v ) == 'table'
|
||||||
|
and v._merge ~= false
|
||||||
|
then
|
||||||
|
dv = inherit( { }, dv )
|
||||||
|
dv = inherit( dv, v )
|
||||||
|
cd[ k ] = dv
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return cd
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -174,11 +180,7 @@ local function add
|
|||||||
)
|
)
|
||||||
-- Creates a new config table which inherits all keys/values
|
-- Creates a new config table which inherits all keys/values
|
||||||
-- from integer keyed tables
|
-- from integer keyed tables
|
||||||
local uconfig = config
|
config = flattenInheritance( config )
|
||||||
|
|
||||||
config = { }
|
|
||||||
|
|
||||||
inherit( config, uconfig )
|
|
||||||
|
|
||||||
-- last and least default prototype is inherited
|
-- last and least default prototype is inherited
|
||||||
inherit( config, userenv.default.proto )
|
inherit( config, userenv.default.proto )
|
||||||
|
Loading…
Reference in New Issue
Block a user