This commit is contained in:
Axel Kittenberger 2010-11-02 14:11:26 +00:00
parent d514669fc0
commit 542bcfa916
1 changed files with 168 additions and 108 deletions

View File

@ -178,108 +178,75 @@ local function globals_lock()
setmetatable(t, mt) setmetatable(t, mt)
end end
-----
-- Holds information about a delayed event for one origin/target.
--
local Delay = (function()
-----
-- Creates a new delay.
--
-- @param TODO
local new = function(ename, pathname, alarm)
local o = {
ename = ename,
alarm = alarm,
pathname = pathname,
}
return o
end
--============================================================================ return {new = new}
-- Lsyncd globals end)()
--============================================================================
----
-- origins
--
-- table of all root directories to sync.
-- filled during initialization.
--
-- [#] {
-- config = config,
-- source = source_dir,
-- targetident = the identifier of target (like string "host:dir")
-- for lsyncd this passed competly opaquely to the
-- action handlers
--
-- .processes = [pid] .. a sublist of processes[] for this target
-- .delays = [#) { .. the delays stack
-- .ename .. enum, kind of action
-- .alarm .. when it should fire
-- .pathname .. complete path relativ to watch origin
-- (.movepeer) .. for MOVEFROM/MOVETO link to other delay
-- }
-- .delayname[pathname] = [#] .. a list of lists of all delays from a
-- its pathname.
-- }
--
local origins = Array.new()
local proto_origin = {
config=true, source=true, targetident=true,
processes=true, delays=true, delayname=true
}
local proto_delay = {
ename =true, alarm=true, pathname=true, movepeer=true
}
----- -----
-- inotifies -- TODO
-- --
-- contains all inotify watches. local Origin = (function()
-- ----
-- structure: -- TODO
-- a list indexed by watch descriptor --
-- [wd] local new = function(source, targetident, config)
-- of a numeric list of all origins watching this dir. local o = {
-- [#] config = config,
-- of inotify { delays = CountArray.new(),
-- .origin .. link to origin delayname = {},
-- .path .. relative path of dir source = source,
-- } targetident = targetident,
-- } processes = CountArray.new(),
-- }
local inotifies = CountArray.new() return o
local proto_inotify = {origin=true, path=true} end
----- -- public interface
-- A list of names of the event types the core sends. return {new = new}
-- (Also makes sure the strings are not collected) end)()
--
local valid_events = {
Attrib = true,
Modify = true,
Create = true,
Delete = true,
Move = true,
MoveFrom = true,
MoveTo = true,
}
--============================================================================
-- The lsyncd runner
--============================================================================
----- -----
-- Puts an action on the delay stack. -- Puts an action on the delay stack.
-- --
local function delay_action(ename, wd, time, origin, pathname, pathname2) function Origin.delay(origin, ename, time, pathname, pathname2)
log(DEBUG, "delay_action "..ename.."("..wd..") ") log(DEBUG, "delay "..ename.." "..pathname)
local o = origin local o = origin
local delays = o.delays local delays = o.delays
local delayname = o.delayname local delayname = o.delayname
if ename == "Move" and not o.config.move then if ename == "Move" and not o.config.move then
-- if there is no move action defined, split a move as delete/create -- if there is no move action defined, split a move as delete/create
log(DEBUG, "splitting Move into Delete & Create") log(DEBUG, "splitting Move into Delete & Create")
delay_action("Delete", wd, time, pathname, nil) delay(o, "Delete", time, pathname, nil)
delay_action("Create", wd, time, pathname2, nil) delay(o, "Create", time, pathname2, nil)
return return
end end
-- creates the new action -- creates the new action
local newd = {ename = ename, local alarm
pathname = pathname } -- TODO scope
set_prototype(newd, proto_delay)
if time and o.config.delay then if time and o.config.delay then
newd.alarm = lsyncd.addto_clock(time, o.config.delay) alarm = lsyncd.addto_clock(time, o.config.delay)
else else
newd.alarm = lsyncd.now() alarm = lsyncd.now()
end end
local newd = Delay.new(ename, pathname, alarm)
local oldd = delayname[pathname] local oldd = delayname[pathname]
if oldd then if oldd then
@ -319,6 +286,117 @@ local function delay_action(ename, wd, time, origin, pathname, pathname2)
end end
end end
-----
-- Origins - a singleton
--
-- It maintains all configured directories to be synced.
--
local Origins = (function()
-- the list of all origins
local list = Array.new()
-- adds a configuration
local add = function(source, targetident, config)
-- absolute path of source
local real_src = lsyncd.real_dir(source)
if not real_src then
log(Error, "Cannot resolve source path: " .. source)
terminate(-1) -- ERRNO
end
config.max_processes =
config.max_processes or
settings.max_processes or
defaults.max_processes
config.collapse_table =
config.collapse_table or
settings.collapse_table or
defaults.collapse_table
config.max_actions = config.max_actions or 1
local o = Origin.new(real_src, targetident, config)
table.insert(list, o)
end
-- allows to walk through all origins
local iwalk = function()
return ipairs(list)
end
-- returns the number of origins
local size = function()
return #list
end
-- public interface
return {add = add, iwalk = iwalk, size = size}
end)()
----
-- origins
--
-- table of all root directories to sync.
-- filled during initialization.
--
-- [#] {
-- config = config,
-- source = source_dir,
-- targetident = the identifier of target (like string "host:dir")
-- for lsyncd this passed competly opaquely to the
-- action handlers
--
-- .processes = [pid] .. a sublist of processes[] for this target
-- .delays = [#) { .. the delays stack
-- .ename .. enum, kind of action
-- .alarm .. when it should fire
-- .pathname .. complete path relativ to watch origin
-- (.movepeer) .. for MOVEFROM/MOVETO link to other delay
-- }
-- .delayname[pathname] = [#] .. a list of lists of all delays from a
-- its pathname.
-- }
--
-----
-- inotifies
--
-- contains all inotify watches.
--
-- structure:
-- a list indexed by watch descriptor
-- [wd]
-- of a numeric list of all origins watching this dir.
-- [#]
-- of inotify {
-- .origin .. link to origin
-- .path .. relative path of dir
-- }
-- }
--
local inotifies = CountArray.new()
local proto_inotify = {origin=true, path=true}
-----
-- A list of names of the event types the core sends.
-- (Also makes sure the strings are not collected)
--
local valid_events = {
Attrib = true,
Modify = true,
Create = true,
Delete = true,
Move = true,
MoveFrom = true,
MoveTo = true,
}
--============================================================================
-- The lsyncd runner
--============================================================================
---- ----
-- Adds watches for a directory including all subdirectories. -- Adds watches for a directory including all subdirectories.
-- --
@ -347,7 +425,8 @@ local function inotify_watch_dir(origin, path)
-- on a warmstart add a Create for the directory -- on a warmstart add a Create for the directory
if not origin.config.startup then if not origin.config.startup then
delay_action("Create", wd, sync, nil, nil, nil) -- TODO BROKEN
origin:delay("Create", sync, nil, nil, nil)
end end
-- registers and adds watches for all subdirectories -- registers and adds watches for all subdirectories
@ -364,7 +443,7 @@ end
function lsyncd_collect_process(pid, exitcode) function lsyncd_collect_process(pid, exitcode)
local delay = nil local delay = nil
local origin = nil local origin = nil
for _, o in ipairs(origins) do for _, o in Origins.iwalk() do
delay = o.processes[pid] delay = o.processes[pid]
if delay then if delay then
origin = o origin = o
@ -456,7 +535,7 @@ end
function lsyncd_alarm(now) function lsyncd_alarm(now)
-- goes through all targets and spawns more actions -- goes through all targets and spawns more actions
-- if possible -- if possible
for _, o in ipairs(origins) do for _, o in Origins.iwalk() do
if o.processes.size < o.config.max_processes then if o.processes.size < o.config.max_processes then
local delays = o.delays local delays = o.delays
local d = delays[1] local d = delays[1]
@ -540,17 +619,16 @@ function lsyncd_initialize(args)
end end
-- makes sure the user gave lsyncd anything to do -- makes sure the user gave lsyncd anything to do
if #origins == 0 then if Origins.size() == 0 then
log(ERROR, "Nothing to watch!") log(ERROR, "Nothing to watch!")
log(ERROR, "Use sync(SOURCE, TARGET, BEHAVIOR) in your config file."); log(ERROR, "Use sync(SOURCE, TARGET, BEHAVIOR) in your config file.");
terminate(-1) -- ERRNO terminate(-1) -- ERRNO
end end
-- 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 _, o in ipairs(origins) do for _, o in Origins.iwalk() do
-- resolves source to be an absolute path -- resolves source to be an absolute path
local asrc = lsyncd.real_dir(o.source) local asrc = lsyncd.real_dir(o.source)
local config = o.config local config = o.config
@ -586,7 +664,7 @@ function lsyncd_initialize(args)
if have_startup then if have_startup then
log(NORMAL, "--- startup ---") log(NORMAL, "--- startup ---")
local pids = { } local pids = { }
for _, o in ipairs(origins) do for _, o in Origins.iwalk() do
local pid local pid
if o.config.startup then if o.config.startup then
local pid = o.config.startup(o.source, o.targetident) local pid = o.config.startup(o.source, o.targetident)
@ -612,7 +690,7 @@ end
function lsyncd_get_alarm() 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 Origins.iwalk() do
if o.delays[1] and if o.delays[1] and
o.processes.size < o.config.max_processes then o.processes.size < o.config.max_processes then
if have_alarm then if have_alarm then
@ -664,7 +742,7 @@ function lsyncd_event(ename, wd, isdir, time, filename, filename2)
if filename2 then if filename2 then
pathname2 = inotify.path..filename2 pathname2 = inotify.path..filename2
end end
delay_action(ename, wd, time, inotify.origin, Origin.delay(inotify.origin, ename, time,
inotify.path..filename, pathname2) inotify.path..filename, pathname2)
-- add subdirs for new directories -- add subdirs for new directories
if isdir then if isdir then
@ -698,25 +776,7 @@ end
-- lsyncd user interface -- lsyncd user interface
--============================================================================ --============================================================================
---- sync = Origins.add
-- Adds one directory (incl. subdirs) to be synchronized.
-- Users primary configuration device.
--
-- @param TODO
--
function sync(source_dir, target_identifier, config)
local o = { config = config,
source = source_dir,
targetident = target_identifier,
}
set_prototype(o, proto_origin)
if not config.max_actions then
config.max_actions = 1 -- TODO move to init
end
table.insert(origins, o)
return
end
---- ----
-- Called by core when an overflow happened. -- Called by core when an overflow happened.