This commit is contained in:
Axel Kittenberger 2010-11-10 22:03:02 +00:00
parent 6efa44f505
commit 219da8d754
3 changed files with 122 additions and 62 deletions

View File

@ -22,7 +22,7 @@ slowbash = {
log("Normal", "cp -r from ", c.source, " -> ", c.target)
-- collect gets called when spawned process finished
local function collect(exitcode)
local function collect(event, exitcode)
if exitcode == 0 then
log("Normal", "Startup of '",c.source,"' finished.")
else

View File

@ -975,7 +975,7 @@ handle_event(lua_State *L, struct inotify_event *event) {
}
/* and hands over to runner */
load_runner_func(L, "inotify_event"); // TODO CamelCase
load_runner_func(L, "inotifyEvent");
switch(event_type) {
case ATTRIB : lua_pushstring(L, "Attrib"); break;
case MODIFY : lua_pushstring(L, "Modify"); break;
@ -1023,7 +1023,7 @@ masterloop(lua_State *L)
ssize_t len;
/* queries runner about soonest alarm */
load_runner_func(L, "get_alarm"); // TODO CamelCase
load_runner_func(L, "getAlarm");
if (lua_pcall(L, 0, 1, -2)) {
exit(-1); // ERRNO
}
@ -1119,7 +1119,7 @@ masterloop(lua_State *L)
if (pid <= 0) {
break;
}
load_runner_func(L, "collect_process"); // TODO CamelCase
load_runner_func(L, "collectProcess");
lua_pushinteger(L, pid);
lua_pushinteger(L, WEXITSTATUS(status));
if (lua_pcall(L, 2, 0, -4)) {
@ -1130,7 +1130,7 @@ masterloop(lua_State *L)
/* lets the runner do stuff every cycle,
* like starting new processes, writing the statusfile etc. */
load_runner_func(L, "cycle"); // TODO CamelCase
load_runner_func(L, "cycle");
lua_pushinteger(L, times(NULL));
if (lua_pcall(L, 1, 0, -3)) {
exit(-1); // ERRNO

View File

@ -170,12 +170,7 @@ local function lockGlobals()
end
-----
-- Holds information about a delayed event for one Sync.
--
-- valid stati are:
-- delay
-- active
-- TODO
-- Holds information about a delayed event of one Sync.
--
local Delay = (function()
-----
@ -184,10 +179,34 @@ local Delay = (function()
-- @param TODO
local function new(etype, alarm, path, path2)
local o = {
-----
-- Type of event.
-- Can be 'Create', 'Modify', 'Attrib', 'Delete' and 'Move'
etype = etype,
-----
-- Latest point in time this should be catered for.
-- This value is in kernel ticks, return of the C's
-- times(NULL) call.
alarm = alarm,
-----
-- path and filename or dirname of the delay relative
-- to the syncs root.
-- for the directories it contains a trailing slash
--
path = path,
------
-- only not nil for 'Move's.
-- path and file/dirname of a move destination.
--
path2 = path2,
------
-- Status of the event
-- valid stati are: 'wait' and 'active'
--
status = "wait",
}
return o
@ -199,7 +218,7 @@ end)()
-----
-- User interface to grap events
--
-- InletControl is the Luas runner part to control the interface
-- InletControl is the runners part to control the interface
-- hidden from the user.
--
local Inlet, InletControl = (function()
@ -233,8 +252,15 @@ local Inlet, InletControl = (function()
end
-----
-- Interface for the user to get fields.
-- Interface for userscripts to get event fields..
--
local eventFields = {
-----
-- Returns a copy of the configuration as called by sync.
-- But including all inherited data and default values.
--
-- TODO give user a readonly version.
--
config = function(event)
return event[delayKey].sync.config
end,
@ -242,17 +268,19 @@ local Inlet, InletControl = (function()
-----
-- Returns the type of the event.
-- Can be:
-- "Attrib"
-- "Create"
-- "Delete"
-- "Modify"
-- "Attrib",
-- "Create",
-- "Delete",
-- "Modify",
-- "Move"
--
etype = function(event)
return event[delayKey].etype
end,
-----
-- Returns true if event relates to a directory.
--
isdir = function(event)
return string.byte(getPath(event), -1) == 47
end,
@ -260,6 +288,7 @@ local Inlet, InletControl = (function()
-----
-- Returns the name of the file/dir.
-- Includes a trailing slash for dirs.
--
name = function(event)
return string.match(getPath(event), "[^/]+/?$")
end,
@ -267,6 +296,7 @@ local Inlet, InletControl = (function()
-----
-- Returns the name of the file/dir.
-- Excludes a trailing slash for dirs.
--
basename = function(event)
return string.match(getPath(event), "([^/]+)/?$")
end,
@ -274,6 +304,7 @@ local Inlet, InletControl = (function()
-----
-- Returns the file/dir relative to watch root
-- Includes a trailing slash for dirs.
--
path = function(event)
return getPath(event)
end,
@ -281,6 +312,7 @@ local Inlet, InletControl = (function()
-----
-- Returns the file/dir relativ to watch root
-- Excludes a trailing slash for dirs.
--
pathname = function(event)
return cutSlash(getPath(event))
end,
@ -288,6 +320,7 @@ local Inlet, InletControl = (function()
------
-- Returns the absolute path of the watch root.
-- All symlinks will have been resolved.
--
source = function(event)
return sync.source
end,
@ -295,6 +328,7 @@ local Inlet, InletControl = (function()
------
-- Returns the absolute path of the file/dir.
-- Includes a trailing slash for dirs.
--
sourcePath = function(event)
return sync.source ..getPath(event)
end,
@ -302,6 +336,7 @@ local Inlet, InletControl = (function()
------
-- Returns the absolute path of the file/dir.
-- Excludes a trailing slash for dirs.
--
sourcePathname = function(event)
return sync.source .. cutSlash(getPath(event))
end,
@ -312,6 +347,7 @@ local Inlet, InletControl = (function()
-- (Actually except of here, the lsyncd.runner itself
-- does not care event about the existance of "target",
-- this is completly up to the action scripts.)
--
target = function(event)
return sync.config.target
end,
@ -319,6 +355,7 @@ local Inlet, InletControl = (function()
------
-- Returns the relative dir/file appended to the target.
-- Includes a trailing slash for dirs.
--
targetPath = function(event)
return sync.config.target .. getPath(event)
end,
@ -326,13 +363,15 @@ local Inlet, InletControl = (function()
------
-- Returns the relative dir/file appended to the target.
-- Excludes a trailing slash for dirs.
--
targetPathname = function(event)
return sync.config.target .. cutSlash(getPath(event))
end,
}
-----
-- Calls event functions for the user.
-- Retrievs event fields for the user.
--
local eventMeta = {
__index = function(t, k)
local f = eventFields[k]
@ -390,7 +429,7 @@ local Inlet, InletControl = (function()
end
-----
-- Gets the next event from queue.
-- Gets the next not blocked event from queue.
--
local function getEvent()
return toEvent(sync:getNextDelay(lysncd.now()))
@ -439,7 +478,8 @@ end)()
local Sync = (function()
-----
-- Syncs that have no name specified get an incremental default name
-- Syncs that have no name specified by the user script
-- get an incremental default name 'Sync[X]'
--
local nextDefaultName = 1
@ -455,7 +495,18 @@ local Sync = (function()
if delay.status ~= "active" then
error("internal fail, collecting a non-active process")
end
-- TODO call user collector
if delay.collector then
local cr
if type(delay.collector) == "function" then
InletControl.setSync(self)
cr = delay.collector(InletControl.toEvent(delay), exitcode)
else
cr = delay.collector
end
end
-- TODO honor return codes of the collector
-- Remove the delay.
local found
for i, d in ipairs(self.delays) do
if d == delay then
@ -467,7 +518,7 @@ local Sync = (function()
if not found then
error("Did not find a delay!")
end
log("Normal","Return of ",delay.etype," on ",
log("Delay","Finish of ",delay.etype," on ",
self.source,delay.path," = ",exitcode)
self.processes[pid] = nil
end
@ -483,7 +534,7 @@ local Sync = (function()
if etype == "Move" and not self.config.onMove then
-- if there is no move action defined, split a move as delete/create
log("Debug", "splitting Move into Delete & Create")
log("Delay", "splitting Move into Delete & Create")
delay(self, "Delete", time, path, nil)
delay(self, "Create", time, path2, nil)
return
@ -498,8 +549,15 @@ local Sync = (function()
end
-- new delay
local nd = Delay.new(etype, alarm, path, path2)
if nd.etype == "Blanket" then
-- always stack blanket events.
log("Delay", "Stacking blanket event.")
table.insert(self.delays, nd)
return
end
if nd.etype == "Move" then
log("Normal", "Stacking a move event ",path," -> ",path2)
log("Delay", "Stacking a move event ",path," -> ",path2)
table.insert(self.delays, nd)
return
end
@ -511,41 +569,44 @@ local Sync = (function()
local ne = InletControl.toEvent(nd)
local il = #self.delays -- last delay
-----
-- TODO
--
local function doCollapse(oe, ne)
end
while il > 0 do
local od = self.delays[il]
-- tries to collapse identical paths
local oe, oe2 = InletControl.toEvent(od)
local ne = InletControl.toEvent(nd) -- TODO more logic on moves
if oe.etype == "Blanket" then
-- everything is blocked by a blanket event.
log("Delay", "Stacking ",nd.etype," upon blanket event.")
table.insert(self.delays, nd)
return
end
-- this mini loop repeats the collapse a second
-- time for move events
local oel = oe
-- this mini loop repeats the collapse a second time for move
-- events
while oel do
local c = self.config.collapse(oel, ne, self.config)
if c == 0 then
-- events nullificate each ether
od.etype = "None" -- TODO better remove?
return "return"
return
elseif c == 1 then
log("Normal", nd.etype, " is absored by event ",
od.etype, " on ", path)
return "return"
log("Delay",nd.etype," is absored by event ",
od.etype," on ",path)
return
elseif c == 2 then
log("Normal", nd.etype, " replaces event ",
od.etype, " on ", path)
log("Delay",nd.etype," replaces event ",
od.etype," on ",path)
self.delays[il] = nd
return "return"
return
elseif c == 3 then
log("Normal", "Stacking ", nd.etype, " upon ",
od.etype, " on ", path)
return "break"
end
log("Delay", "Stacking ",nd.etype," upon ",
od.etype," on ",path)
break
end
-- after first iteration check move destination
-- after second stop eitherway
if oel == oe2 then
oel = false
else
@ -555,13 +616,13 @@ local Sync = (function()
il = il - 1
end
if il <= 0 then
log("Normal", "Stacking ", nd.etype, " upon on ", path)
log("Delay", "Stacking ",nd.etype," on ",path)
end
-- there was no hit on collapse or it decided to stack.
table.insert(self.delays, nd)
end
-----
-----
-- Returns the nearest alarm for this Sync.
--
local function getAlarm(self)
@ -623,7 +684,7 @@ local Sync = (function()
-- (used in startup)
--
local function addBlanketDelay(self)
local newd = Delay.new("Blanket", true, "/")
local newd = Delay.new("Blanket", true, "")
table.insert(self.delays, newd)
return newd
end
@ -712,7 +773,7 @@ local Syncs = (function()
-----
-- raises an error if @param name isnt in opts
local function require_opt(name)
local function requireOpt(name)
if not config[name] then
local info = debug.getinfo(3, "Sl")
log("Error", info.short_src, ":", info.currentline,
@ -720,16 +781,16 @@ local Syncs = (function()
terminate(-1) -- ERRNO
end
end
require_opt("source")
requireOpt("source")
-- absolute path of source
local real_src = lsyncd.realdir(config.source)
if not real_src then
local realsrc = lsyncd.realdir(config.source)
if not realsrc then
log("Error", "Cannot access source directory: ",config.source)
terminate(-1) -- ERRNO
end
config._source = config.source
config.source = real_src
config.source = realsrc
if not config.action and not config.onAttrib and
not config.onCreate and not config.onModify and
@ -876,7 +937,7 @@ local Inotifies = (function()
-- Called when an event has occured.
--
-- @param etype "Attrib", "Mofify", "Create", "Delete", "Move")
-- @param wd watch descriptor (matches lsyncd.add_watch())
-- @param wd watch descriptor (matches lsyncd.inotifyadd())
-- @param isdir true if filename is a directory
-- @param time time of event
-- @param filename string filename without path
@ -1028,8 +1089,8 @@ end)()
--============================================================================
-----
-- true after lsyncd_initalized()
-- TODO change to string
-- true after runner.initalized()
-- TODO change to string X2
--
local running = false
@ -1060,7 +1121,7 @@ end
-- Called from code whenever a child process finished and
-- zombie process was collected by core.
--
function runner.collect_process(pid, exitcode)
function runner.collectProcess(pid, exitcode)
for _, s in Syncs.iwalk() do
if s:collect(pid, exitcode) then
return
@ -1088,7 +1149,6 @@ function runner.cycle(now)
if settings.statusfile then
StatusFile.write(now)
end
log("Debug", "fin lsyncd_cycle")
end
@ -1160,7 +1220,7 @@ function runner.configure(args)
end
if #nonopts == 0 then
lsyncd_help(args[0])
runner.help(args[0])
elseif #nonopts == 1 then
return nonopts[1]
else
@ -1215,7 +1275,7 @@ end
-- true ... immediate action
-- times ... the alarm time (only read if number is 1)
--
function runner.get_alarm()
function runner.getAlarm()
local alarm = false
----
@ -1240,7 +1300,7 @@ function runner.get_alarm()
-- checks if a statusfile write has been delayed
checkAlarm(StatusFile.getAlarm())
log("Debug", "lysncd_get_alarm returns: ",alarm)
log("Debug", "getAlarm returns: ",alarm)
return alarm
end
@ -1248,7 +1308,7 @@ end
-----
-- Called when an inotify event arrived.
-- Simply forwards it directly to the object.
runner.inotify_event = Inotifies.event
runner.inotifyEvent = Inotifies.event
-----
-- Collector for every child process that finished in startup phase
@ -1403,10 +1463,10 @@ default = {
-----
-- Block events if one is a parent directory of another
--
if event1.isdir and string.start(event2.path, event1.path) then
if event1.isdir and string.starts(event2.path, event1.path) then
return 3
end
if event2.isdir and string.start(event1.path, event2.path) then
if event2.isdir and string.starts(event1.path, event2.path) then
return 3
end