This commit is contained in:
Axel Kittenberger 2010-10-26 11:26:57 +00:00
parent 0bf3e14cec
commit 34753fa43c

View File

@ -14,7 +14,7 @@
-- A security measurement. -- A security measurement.
-- Core will exit if version ids mismatch. -- Core will exit if version ids mismatch.
-- --
if lsyncd_version ~= nil then if lsyncd_version then
-- checks if the runner is being loaded twice -- checks if the runner is being loaded twice
print("You cannot use the lsyncd runner as configuration file!") print("You cannot use the lsyncd runner as configuration file!")
os.exit(-1) os.exit(-1)
@ -205,10 +205,12 @@ end
-- .filename .. filename or nil (=dir itself) -- .filename .. filename or nil (=dir itself)
-- (.movepeer) .. for MOVEFROM/MOVETO link to other delay -- (.movepeer) .. for MOVEFROM/MOVETO link to other delay
-- } -- }
-- .delaywd [wd] = [#] .. a list of lists of all delays from a watch descriptor.
-- } -- }
-- --
local origins = new_array() local origins = new_array()
local proto_delay = {atype=true, alarm=true, wd=true, sync=true, filename=true, movepeer=true} local proto_origin = {actions=true, source=true, targetident=true, processes=true, delays=true, delaywd=true}
local proto_delay = {atype =true, alarm=true, wd=true, sync=true, filename=true, movepeer=true}
----- -----
-- all watches -- all watches
@ -243,16 +245,6 @@ local proto_sync = {origin=true, path=true, parent=true}
local processes = new_count_array() local processes = new_count_array()
local proto_process = {pid=true, atype=true, wd=true, sync=true, filename=true} local proto_process = {pid=true, atype=true, wd=true, sync=true, filename=true}
------
-- TODO
--
local collapse_table = {
[ATTRIB] = { [ATTRIB] = ATTRIB, [MODIFY] = MODIFY, [CREATE] = CREATE, [DELETE] = DELETE },
[MODIFY] = { [ATTRIB] = MODIFY, [MODIFY] = MODIFY, [CREATE] = CREATE, [DELETE] = DELETE },
[CREATE] = { [ATTRIB] = CREATE, [MODIFY] = CREATE, [CREATE] = CREATE, [DELETE] = DELETE },
[DELETE] = { [ATTRIB] = DELETE, [MODIFY] = DELETE, [CREATE] = MODIFY, [DELETE] = DELETE },
}
set_array(collapse_table)
----- -----
-- A list of names of the event types the core sends. -- A list of names of the event types the core sends.
@ -277,19 +269,61 @@ set_array(event_names)
-- --
local function delay_action(atype, wd, sync, filename, time) local function delay_action(atype, wd, sync, filename, time)
log(DEBUG, "delay_action "..event_names[atype].."("..wd..") ") log(DEBUG, "delay_action "..event_names[atype].."("..wd..") ")
local origin = sync.origin local o = sync.origin
local delays = origin.delays local delays = o.delays
local nd = {atype = atype, local delaywd = o.delaywd
wd = wd, local newd = {atype = atype,
sync = sync, wd = wd,
filename = filename } sync = sync,
set_prototype(nd, proto_delay) filename = filename }
if time ~= nil and origin.actions.delay ~= nil then set_prototype(newd, proto_delay)
nd.alarm = lsyncd.addto_clock(time, origin.actions.delay) if time and o.actions.delay then
newd.alarm = lsyncd.addto_clock(time, o.actions.delay)
else else
nd.alarm = lsyncd.now() newd.alarm = lsyncd.now()
end
local dwd = delaywd[wd]
if not dwd then
dwd = {}
delaywd[wd] = dwd
end
-- TODO COLLAPSE
if dwd[filename] then
local oldd = dwd[filename]
if newd.atype == MOVE_FROM or newd.atype == MOVE_TO or
oldd.atype == MOVE_FROM or oldd.atype == MOVE_TO then
-- do not collapse moves
log(NORMAL, "Not collapsing events with moves on "..filename)
-- TODO stackinfo
return
else
local col = o.actions.collapse_table[oldd.atype][newd.atype]
if col == -1 then
-- events cancel each other
log(NORMAL, "Nullfication: " ..event_names[newd.atype].." after "..
event_names[oldd.atype].." on "..filename)
oldd.atype = NONE
return
elseif col == 0 then
-- events tack
log(NORMAL, "Stacking " ..event_names[newd.atype].." after "..
event_names[oldd.atype].." on "..filename)
-- TODO stackinfo
else
log(NORMAL, "Collapsing "..event_names[newd.atype].." upon "..
event_names[oldd.atype].." to " ..
event_names[col].." on "..filename)
oldd.atype = col
return
end
end
table.insert(delays, newd)
else
dwd[filename] = newd
table.insert(delays, newd)
end end
table.insert(delays, nd)
end end
---- ----
@ -310,7 +344,7 @@ local function attend_dir(origin, path, parent)
end end
local thiswatch = watches[wd] local thiswatch = watches[wd]
if thiswatch == nil then if not thiswatch then
-- new watch -- new watch
thiswatch = {wd = wd, syncs = {} } thiswatch = {wd = wd, syncs = {} }
set_prototype(thiswatch, proto_watch) set_prototype(thiswatch, proto_watch)
@ -321,7 +355,7 @@ local function attend_dir(origin, path, parent)
table.insert(thiswatch.syncs, sync) table.insert(thiswatch.syncs, sync)
-- warmstart? -- warmstart?
if origin.actions.startup == nil then if not origin.actions.startup then
delay_action(CREATE, wd, sync, nil, nil) delay_action(CREATE, wd, sync, nil, nil)
end end
@ -339,7 +373,7 @@ end
function lsyncd_collect_process(pid, exitcode) function lsyncd_collect_process(pid, exitcode)
log(DEBUG, "collected "..pid) log(DEBUG, "collected "..pid)
local process = processes[pid] local process = processes[pid]
if process == nil then if not process then
return return
end end
local sync = process.sync local sync = process.sync
@ -358,37 +392,26 @@ local function invoke_action(delay)
local origin = sync.origin local origin = sync.origin
local actions = origin.actions local actions = origin.actions
local func = nil local func = nil
if delay.atype == CREATE then local atype = delay.atype
if actions.create ~= nil then if atype == NONE then
func = actions.create -- a removed action
elseif actions.default ~= nil then return
func = actions.default elseif atype == CREATE then
end func = actions.create or actions.default
elseif delay.atype == ATTRIB then elseif atype == ATTRIB then
if actions.attrib ~= nil then func = actions.attrib or actions.default
func = actions.attrib elseif atype == MODIFY then
elseif actions.default ~= nil then func = actions.modify or actions.default
func = actions.default elseif atype == DELETE then
end func = actions.delete or actions.default
elseif delay.atype == MODIFY then elseif atype == MOVE then
if actions.modify ~= nil then log(ERROR, "MOVE NOT YET IMPLEMENTED!") -- TODO
func = actions.modify return
elseif actions.default ~= nil then
func = actions.default
end
elseif delay.atype == DELETE then
if actions.delete ~= nil then
func = actions.delete
elseif actions.default ~= nil then
func = actions.default
end
elseif delay.atype == MOVE then
log(ERROR, "MOVE NOT YET IMPLEMENTED!")
end end
if func ~= nil then if func then
local pid = func(origin.source, sync.path, delay.filename, origin.targetident) local pid = func(origin.source, sync.path, delay.filename, origin.targetident)
if pid ~= nil and pid > 0 then if pid and pid > 0 then
local process = {pid = pid, local process = {pid = pid,
atype = delay.atype, atype = delay.atype,
wd = delay.wd, wd = delay.wd,
@ -415,9 +438,11 @@ function lsyncd_alarm(now)
for _, o in ipairs(origins) do for _, o in ipairs(origins) do
if o.processes.size < o.actions.max_processes then if o.processes.size < o.actions.max_processes then
local delays = o.delays local delays = o.delays
if delays[1] ~= nil and lsyncd.before_eq(delays[1].alarm, now) then local d = delays[1]
invoke_action(o.delays[1]) if d and lsyncd.before_eq(d.alarm, now) then
invoke_action(d)
table.remove(delays, 1) table.remove(delays, 1)
o.delaywd[d.wd][d.filename] = nil
end end
end end
end end
@ -441,36 +466,44 @@ function lsyncd_initialize(args)
-- set to true if at least one origin has a startup function -- set to true if at least one origin has a startup function
local have_startup = false local have_startup = false
-- runs through the origins table filled by user calling directory() -- runs through the origins table filled by user calling directory()
for _, origin in ipairs(origins) do for _, o in ipairs(origins) do
-- resolves source to be an absolute path -- resolves source to be an absolute path
local asrc = lsyncd.real_dir(origin.source) local asrc = lsyncd.real_dir(o.source)
local actions = origin.actions local actions = o.actions
if asrc == nil then if not asrc then
print("Cannot resolve source path: ", origin.source) print("Cannot resolve source path: ", o.source)
lsyncd.terminate(-1) -- ERRNO lsyncd.terminate(-1) -- ERRNO
end end
origin.source = asrc o.source = asrc
origin.delays = new_count_array() o.delays = new_count_array()
origin.processes = new_count_array() o.delaywd = new_array()
o.processes = new_count_array()
if actions.max_processes == nil then actions.max_processes =
actions.max_processes = 1 -- TODO DEFAULT MAXPROCESS actions.max_processes or
end settings.max_processes or
if actions.startup ~= nil then defaults.max_processes
actions.collapse_table =
actions.collapse_table or
settings.collapse_table or
defaults.collapse_table
if actions.startup then
have_startup = true have_startup = true
end end
-- and add the dir watch inclusively all subdirs -- and add the dir watch inclusively all subdirs
attend_dir(origin, "", nil) attend_dir(o, "", nil)
end end
if have_startup then if have_startup then
log(NORMAL, "--- startup ---") log(NORMAL, "--- startup ---")
local pids = { } local pids = { }
for _, origin in ipairs(origins) do for _, o in ipairs(origins) do
local pid local pid
if origin.actions.startup ~= nil then if o.actions.startup then
local pid = origin.actions.startup(origin.source, origin.targetident) local pid = o.actions.startup(o.source, o.targetident)
table.insert(pids, pid) table.insert(pids, pid)
end end
end end
@ -492,7 +525,7 @@ function lsyncd_get_alarm()
local have_alarm = false local have_alarm = false
local alarm = 0 local alarm = 0
for _, o in ipairs(origins) do for _, o in ipairs(origins) do
if o.delays[1] ~= nil and if o.delays[1] and
o.processes.size < o.actions.max_processes then o.processes.size < o.actions.max_processes then
if have_alarm then if have_alarm then
alarm = lsyncd.earlier(alarm, o.delays[1].alarm) alarm = lsyncd.earlier(alarm, o.delays[1].alarm)
@ -522,15 +555,15 @@ function lsyncd_event(etype, wd, isdir, time, filename, filename2)
ftype = "file" ftype = "file"
end end
-- TODO comment out to safe performance -- TODO comment out to safe performance
if filename2 == nil then if filename2 then
log(DEBUG, "got event "..event_names[etype].." of "..ftype.." "..filename)
else
log(DEBUG, "got event "..event_names[etype].." of "..ftype.." "..filename.." to "..filename2) log(DEBUG, "got event "..event_names[etype].." of "..ftype.." "..filename.." to "..filename2)
else
log(DEBUG, "got event "..event_names[etype].." of "..ftype.." "..filename)
end end
-- looks up the watch descriptor id -- looks up the watch descriptor id
local w = watches[wd] local w = watches[wd]
if w == nil then if not w then
log(NORMAL, "event belongs to unknown or deleted watch descriptor.") log(NORMAL, "event belongs to unknown or deleted watch descriptor.")
return return
end end
@ -580,8 +613,10 @@ function sync(source_dir, target_identifier, actions)
source = source_dir, source = source_dir,
targetident = target_identifier, targetident = target_identifier,
} }
if actions.max_actions == nil then set_prototype(o, proto_origin)
actions.max_actions = 1
if not actions.max_actions then
actions.max_actions = 1 -- TODO move to init
end end
table.insert(origins, o) table.insert(origins, o)
return return
@ -596,4 +631,24 @@ function default_overflow()
end end
overflow = default_overflow overflow = default_overflow
--============================================================================
-- lsyncd default settings
--============================================================================
defaults = {
-----
-- TODO
--
max_processes = 1,
------
-- TODO
--
collapse_table = {
[ATTRIB] = { [ATTRIB] = ATTRIB, [MODIFY] = MODIFY, [CREATE] = CREATE, [DELETE] = DELETE },
[MODIFY] = { [ATTRIB] = MODIFY, [MODIFY] = MODIFY, [CREATE] = CREATE, [DELETE] = DELETE },
[CREATE] = { [ATTRIB] = CREATE, [MODIFY] = CREATE, [CREATE] = CREATE, [DELETE] = -1 },
[DELETE] = { [ATTRIB] = DELETE, [MODIFY] = DELETE, [CREATE] = MODIFY, [DELETE] = DELETE },
}
}