This commit is contained in:
Axel Kittenberger 2010-11-12 09:45:22 +00:00
parent 0a6fac9c0c
commit daa7aa22ee
3 changed files with 94 additions and 49 deletions

View File

@ -17,6 +17,8 @@ prefix = "sleep 1 && "
slowbash = { slowbash = {
delay = 5, delay = 5,
maxProcesses = 5,
onStartup = function(event) onStartup = function(event)
log("Normal", "cp -r from ", event.source, " -> ", event.target) log("Normal", "cp -r from ", event.source, " -> ", event.target)
spawnShell(event, spawnShell(event,

View File

@ -903,8 +903,6 @@ handle_event(lua_State *L,
/* used to execute two events in case of unmatched MOVE_FROM buffer */ /* used to execute two events in case of unmatched MOVE_FROM buffer */
struct inotify_event *after_buf = NULL; struct inotify_event *after_buf = NULL;
logstring("Inotify", "got an event");
if (reset) { if (reset) {
return; return;
} }
@ -921,6 +919,11 @@ handle_event(lua_State *L,
if (event && (IN_IGNORED & event->mask)) { if (event && (IN_IGNORED & event->mask)) {
return; return;
} }
if (event && event->len == 0) {
/* sometimes inotify sends such strange events,
* (e.g. when touching a dir */
return;
}
if (event == NULL) { if (event == NULL) {
/* a buffered MOVE_FROM is not followed by anything, /* a buffered MOVE_FROM is not followed by anything,
@ -1004,9 +1007,9 @@ handle_event(lua_State *L,
exit(-1); // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); lua_pop(L, 1);
/* if there is a buffered event executes it */ /* if there is a buffered event executes it */
if (after_buf) { if (after_buf) {
logstring("Inotify", "handling buffered event.");
handle_event(L, after_buf); handle_event(L, after_buf);
} }
} }
@ -1114,6 +1117,7 @@ masterloop(lua_State *L)
} }
/* checks if there is an unary MOVE_FROM left in the buffer */ /* checks if there is an unary MOVE_FROM left in the buffer */
if (move_event) { if (move_event) {
logstring("Inotify", "handling unary move from.");
handle_event(L, NULL); handle_event(L, NULL);
} }

View File

@ -25,7 +25,7 @@ lsyncd_version = "2.0beta1"
----- -----
-- Hides the core interface from user scripts -- Hides the core interface from user scripts
-- --
_l = lsyncd local _l = lsyncd
lsyncd = nil lsyncd = nil
local lsyncd = _l local lsyncd = _l
_l = nil _l = nil
@ -250,7 +250,7 @@ local Inlet, InletControl = (function()
end end
local function getPath(event) local function getPath(event)
if not event.move then if event.move ~= "To" then
return e2d[event].path return e2d[event].path
else else
return e2d[event].path2 return e2d[event].path2
@ -278,11 +278,23 @@ local Inlet, InletControl = (function()
-- "Create", -- "Create",
-- "Delete", -- "Delete",
-- "Modify", -- "Modify",
-- "Move" -- "MoveFr",
-- "MoveTo"
-- --
etype = function(event) etype = function(event)
return e2d[event].etype return e2d[event].etype
end, end,
-----
-- Returns 'Fr'/'To' for events of moves.
move = function(event)
local d = e2d[event]
if d.move then
return d.move
else
return ""
end
end,
----- -----
-- Status -- Status
@ -399,9 +411,10 @@ local Inlet, InletControl = (function()
} }
----- -----
-- Turns a delay to a event.
-- Encapsulates a delay into an event for the user -- Encapsulates a delay into an event for the user
-- --
local function toEvent(delay) local function d2e(delay)
if delay.etype ~= "Move" then if delay.etype ~= "Move" then
if not delay.event then if not delay.event then
local event = {} local event = {}
@ -424,10 +437,8 @@ local Inlet, InletControl = (function()
e2d[delay.event2] = delay e2d[delay.event2] = delay
-- move events have a field 'event' -- move events have a field 'event'
-- false for move source events event.move = "Fr"
-- true for move desination events event2.move = "To"
event.move = false
event2.move = true
end end
return delay.event, delay.event2 return delay.event, delay.event2
end end
@ -439,7 +450,7 @@ local Inlet, InletControl = (function()
-- and is blocked by everything. -- and is blocked by everything.
-- --
local function createBlanketEvent() local function createBlanketEvent()
return toEvent(sync:addBlanketDelay()) return d2e(sync:addBlanketDelay())
end end
----- -----
@ -459,7 +470,7 @@ local Inlet, InletControl = (function()
-- Gets the next not blocked event from queue. -- Gets the next not blocked event from queue.
-- --
local function getEvent() local function getEvent()
return toEvent(sync:getNextDelay(lysncd.now())) return d2e(sync:getNextDelay(lysncd.now()))
end end
----- -----
@ -495,7 +506,7 @@ local Inlet, InletControl = (function()
}, { }, {
setSync = setSync, setSync = setSync,
getInterior = getInterior, -- TODO <- remove getInterior = getInterior, -- TODO <- remove
toEvent = toEvent, d2e = d2e,
} }
end)() end)()
@ -541,7 +552,7 @@ local Sync = (function()
end end
InletControl.setSync(self) InletControl.setSync(self)
local rc = self.config.collect(InletControl.toEvent(delay), exitcode) local rc = self.config.collect(InletControl.d2e(delay), exitcode)
-- TODO honor return codes of the collect -- TODO honor return codes of the collect
removeDelay(self, delay) removeDelay(self, delay)
log("Delay","Finish of ",delay.etype," on ", log("Delay","Finish of ",delay.etype," on ",
@ -549,17 +560,33 @@ local Sync = (function()
self.processes[pid] = nil self.processes[pid] = nil
end end
-----
-- Stacks a newDelay on the oldDelay,
-- the oldDelay blocks the new Delay.
--
-- A delay can block 'n' other delays,
-- but is blocked at most by one, the latest delay.
--
local function stack(oldDelay, newDelay)
newDelay.status = "block"
if not oldDelay.blocks then
oldDelay.blocks = {}
end
table.insert(oldDelay.blocks, newDelay)
end
----- -----
-- Puts an action on the delay stack. -- Puts an action on the delay stack.
-- --
local function delay(self, etype, time, path, path2) local function delay(self, etype, time, path, path2)
log("Function", "delay(", self.config.name,", ",etype,", ",path,")") log("Function", "delay(", self.config.name,", ",etype,", ",path,")")
if path2 then if path2 then
log("Function", "...delay(+",path2,")") log("Function", "+ ",path2)
end end
if etype == "Move" and not self.config.onMove then if etype == "Move" and not self.config.onMove 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("Delay", "splitting Move into Delete & Create") log("Delay", "splitting Move into Delete & Create")
delay(self, "Delete", time, path, nil) delay(self, "Delete", time, path, nil)
delay(self, "Create", time, path2, nil) delay(self, "Create", time, path2, nil)
@ -576,34 +603,31 @@ local Sync = (function()
-- new delay -- new delay
local nd = Delay.new(etype, alarm, path, path2) local nd = Delay.new(etype, alarm, path, path2)
if nd.etype == "Blanket" then if nd.etype == "Blanket" then
-- always stack blanket events. -- always stack blanket events on the last event
log("Delay", "Stacking blanket event.") log("Delay", "Stacking blanket event.")
table.insert(self.delays, nd) if #self.delays > 0 then
return stack(self.delays[#self.delays], nd)
end end
if nd.etype == "Move" then
log("Delay", "Stacking a move event ",path," -> ",path2)
table.insert(self.delays, nd) table.insert(self.delays, nd)
return return
end end
----- -----
-- detects blocks and collapses by working from back til -- detects blocks and collapses by working from back until
-- front through the fifo -- front through the fifo
InletControl.setSync(self) InletControl.setSync(self)
local ne = InletControl.toEvent(nd) local ne, ne2 = InletControl.d2e(nd)
local il = #self.delays -- last delay local il = #self.delays -- last delay
while il > 0 do while il > 0 do
-- get 'old' delay
local od = self.delays[il] local od = self.delays[il]
-- tries to collapse identical paths -- tries to collapse identical paths
local oe, oe2 = InletControl.toEvent(od) local oe, oe2 = InletControl.d2e(od)
local ne = InletControl.toEvent(nd) -- TODO more logic on moves
if oe.etype == "Blanket" then if oe.etype == "Blanket" then
-- everything is blocked by a blanket event. -- everything is blocked by a blanket event.
log("Delay", "Stacking ",nd.etype," upon blanket event.") log("Delay", "Stacking ",nd.etype," upon blanket event.")
stack(od, nd)
table.insert(self.delays, nd) table.insert(self.delays, nd)
return return
end end
@ -611,8 +635,10 @@ local Sync = (function()
-- this mini loop repeats the collapse a second -- this mini loop repeats the collapse a second
-- time for move events -- time for move events
local oel = oe local oel = oe
while oel do local nel = ne
local c = self.config.collapse(oel, ne, self.config)
while oel and nel do
local c = self.config.collapse(oel, nel, self.config)
if c == 0 then if c == 0 then
-- events nullificate each ether -- events nullificate each ether
od.etype = "None" -- TODO better remove? od.etype = "None" -- TODO better remove?
@ -625,24 +651,30 @@ local Sync = (function()
log("Delay",nd.etype," replaces event ", log("Delay",nd.etype," replaces event ",
od.etype," on ",path) od.etype," on ",path)
self.delays[il] = nd self.delays[il] = nd
-- TODO turn moveFroms into deletes.
return return
elseif c == 3 then elseif c == 3 then
log("Delay", "Stacking ",nd.etype," upon ", log("Delay", "Stacking ",nd.etype," upon ",
od.etype," on ",path) od.etype," on ",path)
stack(od, nd)
break break
end end
-- after first iteration check move destination
-- after second stop eitherway -- loops over all oe, oe2, ne, ne2 combos.
if oel == oe2 then if oel == oe and oe2 then
oel = false -- do another time for oe2 if present
else
oel = oe2 oel = oe2
elseif nel == ne then
-- do another time for ne2 if present
-- start with first oe
nel = ne2
oel = oe
end end
end end
il = il - 1 il = il - 1
end end
if il <= 0 then if il <= 0 then
log("Delay", "Stacking ",nd.etype," on ",path) log("Delay", "Registering ",nd.etype," on ",path)
end end
-- there was no hit on collapse or it decided to stack. -- there was no hit on collapse or it decided to stack.
table.insert(self.delays, nd) table.insert(self.delays, nd)
@ -1496,13 +1528,9 @@ default = {
-- --
collapse = function(event1, event2, config) collapse = function(event1, event2, config)
if event1.path == event2.path then if event1.path == event2.path then
if event1.etype == "Move" or event2.etype == "Move" then local e1 = event1.etype .. event1.move
-- currently moves are always blocks local e2 = event2.etype .. event2.move
return 3 return config.collapseTable[e1][e2]
else
-- asks the collapseTable what to do
return config.collapseTable[event1.etype][event2.etype]
end
end end
----- -----
@ -1519,13 +1547,24 @@ default = {
end, end,
----- -----
-- used by default collapse function -- Used by default collapse function.
-- Specifies how two event should be collapsed when here
-- horizontal event meets upon a vertical event.
-- values:
-- 0 ... nullification of both events.
-- 1 ... absorbtion of horizontal event.
-- 2 ... replace of vertical event.
-- 3 ... stack both events, vertical blocking horizonal.
-- 9 ... combines two move events.
-- --
collapseTable = { collapseTable = {
Attrib = { Attrib = 1, Modify = 2, Create = 2, Delete = 2 }, Attrib = {Attrib=1, Modify=2, Create=2, Delete=2, MoveFr=3, MoveTo= 2},
Modify = { Attrib = 1, Modify = 1, Create = 2, Delete = 2 }, Modify = {Attrib=1, Modify=1, Create=2, Delete=2, MoveFr=3, MoveTo= 2},
Create = { Attrib = 1, Modify = 1, Create = 1, Delete = 0 }, Create = {Attrib=1, Modify=1, Create=1, Delete=0, MoveFr=3, MoveTo= 2},
Delete = { Attrib = 1, Modify = 1, Create = 3, Delete = 1 }, Delete = {Attrib=1, Modify=1, Create=3, Delete=1, MoveFr=3, MoveTo= 2},
MoveFr = {Attrib=3, Modify=3, Create=3, Delete=3, MoveFr=3, MoveTo= 3},
-- MoveTo = {Attrib=3, Modify=3, Create=2, Delete=2, MoveFr=9, MoveTo= 2}, TODO 9
MoveTo = {Attrib=3, Modify=3, Create=2, Delete=2, MoveFr=3, MoveTo= 2},
}, },
----- -----