mirror of https://github.com/octoleo/lsyncd.git
This commit is contained in:
parent
d514669fc0
commit
542bcfa916
276
lsyncd.lua
276
lsyncd.lua
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue