mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-06-11 20:52:23 +00:00
simplifying runners Notifies implementation
This commit is contained in:
parent
1baed5c949
commit
ec336e0ed1
|
@ -115,5 +115,5 @@ convert = {
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
sync{convert, source="magicdir", recursive=false}
|
sync{convert, source="magicdir", subdirs=false}
|
||||||
|
|
||||||
|
|
261
lsyncd.lua
261
lsyncd.lua
|
@ -1401,6 +1401,24 @@ local Syncs = (function()
|
||||||
end)()
|
end)()
|
||||||
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- Utility function, returns the relative part of absolute path if it
|
||||||
|
-- begins with root
|
||||||
|
--
|
||||||
|
local function splitPath(path, root)
|
||||||
|
local rl = #root
|
||||||
|
local sp = string.sub(path, 1, rl)
|
||||||
|
|
||||||
|
print("split", path, root, sp)
|
||||||
|
|
||||||
|
if sp == root then
|
||||||
|
print("splited", path, root, string.sub(path, rl, -1))
|
||||||
|
return string.sub(path, rl, -1)
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- Interface to inotify, watches recursively subdirs and
|
-- Interface to inotify, watches recursively subdirs and
|
||||||
-- sends events.
|
-- sends events.
|
||||||
|
@ -1410,64 +1428,57 @@ end)()
|
||||||
-- by changing this.
|
-- by changing this.
|
||||||
--
|
--
|
||||||
local Inotifies = (function()
|
local Inotifies = (function()
|
||||||
-----
|
|
||||||
-- A list indexed by inotifies watch descriptor.
|
---- XXX wdlist, syncpaths
|
||||||
-- Contains a list of all syncs observing this directory
|
|
||||||
-- (directly or by recurse)
|
|
||||||
local wdlist = CountArray.new()
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- A list indexed by sync's containing a list of all paths
|
-- A list indexed by inotifies watch descriptor yielding the
|
||||||
-- watches by this sync pointing to the watch descriptor.
|
-- directories absolute paths.
|
||||||
local syncpaths = {}
|
|
||||||
|
|
||||||
-----
|
|
||||||
-- Adds watches for a directory including all subdirectories.
|
|
||||||
--
|
--
|
||||||
-- @param root+path directory to observe
|
local wdpaths = CountArray.new()
|
||||||
-- @param recurse true if recursing into subdirs or
|
|
||||||
-- the relative path to root for recursed inotifies
|
|
||||||
-- @param sync link to the observer to be notified.
|
|
||||||
-- Note: Inotifies should handle this opaquely
|
|
||||||
-- @param raise if not nil creates Create events for all files/dirs
|
|
||||||
-- in this directory. Value is time for event.
|
|
||||||
local function addSync(root, path, recurse, sync, raise)
|
|
||||||
log("Function",
|
|
||||||
"Inotifies.addSync(",root,", ",path,", ",recurse,", ",sync,")")
|
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- The same vice versa, all watch descriptors by its
|
||||||
|
-- absolute path.
|
||||||
|
--
|
||||||
|
local pathwds = CountArray.new()
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- A list indexed by sync's containing the root path this
|
||||||
|
-- sync is interested in.
|
||||||
|
--
|
||||||
|
local syncRoots = {}
|
||||||
|
|
||||||
|
-----
|
||||||
|
-- Adds watches for a directory (optionally) including all subdirectories.
|
||||||
|
--
|
||||||
|
-- @param path absolute path of directory to observe
|
||||||
|
-- @param recurse true if recursing into subdirs
|
||||||
|
-- @param raiseSync --X --
|
||||||
|
-- raiseTime if not nil sends create Events for all files/dirs
|
||||||
|
-- to this sync.
|
||||||
|
--
|
||||||
|
local function addWatch(path, recurse, raiseSync, raiseTime)
|
||||||
|
log("Function",
|
||||||
|
"Inotifies.addWatch(",path,", ",recurse,", ",sync,", ",raise")")
|
||||||
|
|
||||||
|
local wd = pathwds[path]
|
||||||
|
if not wd then
|
||||||
-- lets the core registers watch with the kernel
|
-- lets the core registers watch with the kernel
|
||||||
local wd = lsyncd.inotifyadd(root .. path);
|
local wd = lsyncd.inotifyadd(path);
|
||||||
if wd < 0 then
|
if wd < 0 then
|
||||||
log("Error","Failure adding watch ",root,path," -> ignored ")
|
log("Error","Failure adding watch ",path," -> ignored ")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
pathwds[path] = wd
|
||||||
-- creates a sublist in wdlist
|
wdpaths[wd] = path
|
||||||
if not wdlist[wd] then
|
|
||||||
wdlist[wd] = Array.new()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- and adds this sync to wdlist.
|
|
||||||
table.insert(wdlist[wd], {
|
|
||||||
root = root,
|
|
||||||
path = path,
|
|
||||||
recurse = recurse,
|
|
||||||
sync = sync
|
|
||||||
})
|
|
||||||
|
|
||||||
-- creates an entry in syncpaths to quickly retrieve
|
|
||||||
-- all entries of this sync for a path.
|
|
||||||
local sp = syncpaths[sync]
|
|
||||||
if not sp then
|
|
||||||
sp = {}
|
|
||||||
syncpaths[sync] = sp
|
|
||||||
end
|
|
||||||
sp[path] = wd
|
|
||||||
|
|
||||||
-- registers and adds watches for all subdirectories
|
-- registers and adds watches for all subdirectories
|
||||||
-- and/or raises create events for all entries
|
-- and/or raises create events for all entries
|
||||||
if recurse or raise then
|
if recurse or raise then
|
||||||
local entries = lsyncd.readdir(root .. path)
|
local entries = lsyncd.readdir(path)
|
||||||
for dirname, isdir in pairs(entries) do
|
for dirname, isdir in pairs(entries) do
|
||||||
local pd = path .. dirname
|
local pd = path .. dirname
|
||||||
if isdir then
|
if isdir then
|
||||||
|
@ -1475,50 +1486,42 @@ local Inotifies = (function()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- creates a Create event for entry.
|
-- creates a Create event for entry.
|
||||||
if raise then
|
if raiseSync then
|
||||||
sync:delay("Create", raise, pd, nil)
|
raiseSync:delay("Create", raiseTime, pd, nil)
|
||||||
end
|
end
|
||||||
-- adds syncs for subdirs
|
-- adds syncs for subdirs
|
||||||
if isdir and recurse then
|
if isdir and recurse then
|
||||||
addSync(root, pd, true, sync, raise)
|
addWatch(pd, true, raiseSync, raiseTime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- Removes one event receiver from a directory.
|
-- Stops watching a directory
|
||||||
--
|
--
|
||||||
local function removeSync(sync, path)
|
local function removeWatch(path)
|
||||||
local sp = syncpaths[sync]
|
local wd = pathwds[path]
|
||||||
if not sp then
|
|
||||||
error("internal fail, removeSync, nonexisting sync: ")
|
|
||||||
end
|
|
||||||
local wd = sp[path]
|
|
||||||
if not wd then
|
if not wd then
|
||||||
error("internal fail, removeSync, nonexisting wd.")
|
return
|
||||||
end
|
end
|
||||||
local ilist = wdlist[wd]
|
|
||||||
if not ilist then
|
|
||||||
error("internal fail, removeSync, nonexisting ilist.")
|
|
||||||
end
|
|
||||||
-- TODO optimize for 1 entry only case
|
|
||||||
local i, found
|
|
||||||
for i, v in ipairs(ilist) do
|
|
||||||
if v.sync == sync then
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then
|
|
||||||
error("internal fail, removeSync, nonexisiting i.")
|
|
||||||
end
|
|
||||||
table.remove(ilist, i)
|
|
||||||
if #ilist == 0 then
|
|
||||||
wdlist[wd] = nil
|
|
||||||
lsyncd.inotifyrm(wd)
|
lsyncd.inotifyrm(wd)
|
||||||
|
wdpaths[wd] = nil
|
||||||
|
pathwids[path] = nil
|
||||||
end
|
end
|
||||||
sp[path] = nil
|
|
||||||
|
-----
|
||||||
|
-- adds a Sync to receive events
|
||||||
|
--
|
||||||
|
-- @param root root dir to watch
|
||||||
|
-- @param sync Object to receive events
|
||||||
|
--
|
||||||
|
local function addSync(root, sync)
|
||||||
|
if syncRoots[sync] then
|
||||||
|
error("internal fail, duplicate sync in Inotifies()")
|
||||||
|
end
|
||||||
|
syncRoots[sync] = root
|
||||||
|
addWatch(root, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
@ -1533,6 +1536,7 @@ local Inotifies = (function()
|
||||||
--
|
--
|
||||||
local function event(etype, wd, isdir, time, filename, wd2, filename2)
|
local function event(etype, wd, isdir, time, filename, wd2, filename2)
|
||||||
local ftype;
|
local ftype;
|
||||||
|
|
||||||
if isdir then
|
if isdir then
|
||||||
ftype = "directory"
|
ftype = "directory"
|
||||||
filename = filename .. "/"
|
filename = filename .. "/"
|
||||||
|
@ -1540,6 +1544,7 @@ local Inotifies = (function()
|
||||||
filename2 = filename2 .. "/"
|
filename2 = filename2 .. "/"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if filename2 then
|
if filename2 then
|
||||||
log("Inotify", "got event ", etype, " ", filename,
|
log("Inotify", "got event ", etype, " ", filename,
|
||||||
" to ", filename2)
|
" to ", filename2)
|
||||||
|
@ -1548,80 +1553,80 @@ local Inotifies = (function()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- looks up the watch descriptor id
|
-- looks up the watch descriptor id
|
||||||
local ilist = wdlist[wd]
|
local path = wdlist[wd]
|
||||||
if not ilist then
|
if not path then
|
||||||
-- this is normal in case of deleted subdirs
|
-- this is normal in case of deleted subdirs
|
||||||
log("Inotify", "event belongs to unknown watch descriptor.")
|
log("Inotify", "event belongs to unknown watch descriptor.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local ilist2 = wd2 and wdlist[wd2]
|
|
||||||
|
|
||||||
-- works through all observers interested in this directory
|
local path2 = wd2 and wdpaths[wd2]
|
||||||
for _, inotify in ipairs(ilist) do
|
-- set to true if at least one sync wants recursive data
|
||||||
local path = inotify.path .. filename
|
local recurse = false
|
||||||
local path2
|
|
||||||
local etype2 = etype
|
|
||||||
if filename2 and ilist2 then
|
|
||||||
local inotify2
|
|
||||||
-- finds the target directory inotify/watch
|
|
||||||
for _2, i2 in ipairs(ilist2) do
|
|
||||||
if inotify.sync == i2.sync then
|
|
||||||
inotify2 = i2
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not inotify2 then
|
|
||||||
log("Normal", "Transformed move to Create for ",
|
|
||||||
inotify.sync.config.name)
|
|
||||||
etype2 = "Create"
|
|
||||||
else
|
|
||||||
path2 = inotify2.path .. filename2
|
|
||||||
end
|
|
||||||
end
|
|
||||||
inotify.sync:delay(etype2, time, path, path2)
|
|
||||||
|
|
||||||
-- adds subdirs for new directories
|
for sync, root in pairs(syncRoots) do repeat
|
||||||
if isdir and inotify.recurse then
|
local relative = splitPath(path, root)
|
||||||
if etype2 == "Create" then
|
local relative2
|
||||||
addSync(inotify.root, path, true, inotify.sync, time)
|
if path2 then
|
||||||
elseif etype2 == "Delete" then
|
relative2 = splitPath(path2, root)
|
||||||
removeSync(inotify.sync, path)
|
|
||||||
elseif etype2 == "Move" then
|
|
||||||
removeSync(inotify.sync, path)
|
|
||||||
addSync(inotify.root, path2, true, inotify.sync, time)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
if not relative and not relative2 then
|
||||||
|
-- sync is not interested in this dir
|
||||||
|
break -- continue
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO handle cases where a sync watches target only. XXX
|
--- checks if this sync is interested in subdirs
|
||||||
|
if isdir then
|
||||||
|
recurse = recurse or
|
||||||
|
sync.config.subdirs or
|
||||||
|
sync.config.subdirs == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- makes a copy of etype to possibly change it
|
||||||
|
local etyped = etype
|
||||||
|
if etyped == 'Move' then
|
||||||
|
if not relative2 then
|
||||||
|
log("Normal", "Transformed Move to Create for ",
|
||||||
|
sync.config.name)
|
||||||
|
etyped = 'Create'
|
||||||
|
elseif not relative then
|
||||||
|
relative = relative2
|
||||||
|
relative2 = nil
|
||||||
|
log("Normal", "Transformed Move to Delete for ",
|
||||||
|
sync.config.name)
|
||||||
|
etyped = 'Delete'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
sync:delay(etyped, time, relative, relative2)
|
||||||
|
|
||||||
|
if isdir and
|
||||||
|
(sync.config.subdirs or sync.config.subdirs == nil)
|
||||||
|
then
|
||||||
|
if etyped == "Create" then
|
||||||
|
addWatch(path, true, sync, time)
|
||||||
|
elseif etyped == "Delete" then
|
||||||
|
removeWatch(path)
|
||||||
|
elseif etyped == "Move" then
|
||||||
|
removeWatch(path)
|
||||||
|
addWatch(path2, true, sync, time)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
until true end
|
||||||
end
|
end
|
||||||
|
|
||||||
-----
|
-----
|
||||||
-- Writes a status report about inotifies to a filedescriptor
|
-- Writes a status report about inotifies to a filedescriptor
|
||||||
--
|
--
|
||||||
local function statusReport(f)
|
local function statusReport(f)
|
||||||
f:write("Watching ",wdlist:size()," directories\n")
|
f:write("Watching ",wdpaths:size()," directories\n")
|
||||||
for wd, v in wdlist:walk() do
|
for wd, path in wdpaths:walk() do
|
||||||
f:write(" ",wd,": ")
|
f:write(" ",wd,": ",path,"\n")
|
||||||
local sep = ""
|
|
||||||
for _, v in ipairs(v) do
|
|
||||||
f:write(v.root,"/",v.path or "",sep)
|
|
||||||
sep = ", "
|
|
||||||
end
|
end
|
||||||
f:write("\n")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----
|
|
||||||
-- Returns the number of directories watched in total.
|
|
||||||
local function size()
|
|
||||||
return wdlist:size()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- public interface
|
-- public interface
|
||||||
return {
|
return {
|
||||||
addSync = addSync,
|
addSync = addSync,
|
||||||
size = size,
|
|
||||||
event = event,
|
event = event,
|
||||||
statusReport = statusReport
|
statusReport = statusReport
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user