mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-05-29 06:30:46 +00:00
further structering mantle
This commit is contained in:
parent
5771779e28
commit
2f1a1967ab
|
@ -48,8 +48,11 @@ set( LUA_CODE
|
|||
${PROJECT_SOURCE_DIR}/mantle/syncmaster.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/monitor.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/fwriter.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/status.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/statusfile.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/useralarm.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/lsyncd.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/user.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/string.lua
|
||||
${PROJECT_SOURCE_DIR}/mantle/wrapup.lua
|
||||
${PROJECT_SOURCE_DIR}/default/default.lua
|
||||
${PROJECT_SOURCE_DIR}/default/rsync.lua
|
||||
|
|
|
@ -80,197 +80,6 @@ uSettings = { }
|
|||
|
||||
|
||||
|
||||
--============================================================================
|
||||
-- Lsyncd Prototypes
|
||||
--============================================================================
|
||||
|
||||
|
||||
--
|
||||
-- Writes a status report file at most every 'statusintervall' seconds.
|
||||
--
|
||||
local StatusFile = ( function
|
||||
( )
|
||||
--
|
||||
-- Timestamp when the status file has been written.
|
||||
--
|
||||
local lastWritten = false
|
||||
|
||||
--
|
||||
-- Timestamp when a status file should be written.
|
||||
--
|
||||
local alarm = false
|
||||
|
||||
--
|
||||
-- Returns the alarm when the status file should be written-
|
||||
--
|
||||
local function getAlarm
|
||||
( )
|
||||
return alarm
|
||||
end
|
||||
|
||||
--
|
||||
-- Called to check if to write a status file.
|
||||
--
|
||||
local function write
|
||||
(
|
||||
timestamp
|
||||
)
|
||||
log( 'Function', 'write( ', timestamp, ' )' )
|
||||
|
||||
--
|
||||
-- takes care not to write too often
|
||||
--
|
||||
if uSettings.statusInterval > 0
|
||||
then
|
||||
-- already waiting?
|
||||
if alarm and timestamp < alarm
|
||||
then
|
||||
log( 'Statusfile', 'waiting(', timestamp, ' < ', alarm, ')' )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- determines when a next write will be possible
|
||||
if not alarm
|
||||
then
|
||||
local nextWrite = lastWritten and timestamp + uSettings.statusInterval
|
||||
|
||||
if nextWrite and timestamp < nextWrite
|
||||
then
|
||||
log( 'Statusfile', 'setting alarm: ', nextWrite )
|
||||
alarm = nextWrite
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
lastWritten = timestamp
|
||||
alarm = false
|
||||
end
|
||||
|
||||
log( 'Statusfile', 'writing now' )
|
||||
|
||||
local f, err = io.open( uSettings.statusFile, 'w' )
|
||||
|
||||
if not f
|
||||
then
|
||||
log(
|
||||
'Error',
|
||||
'Cannot open status file "' ..
|
||||
uSettings.statusFile ..
|
||||
'" :' ..
|
||||
err
|
||||
)
|
||||
return
|
||||
end
|
||||
|
||||
f:write( 'Lsyncd status report at ', os.date( ), '\n\n' )
|
||||
|
||||
for i, s in SyncMaster.iwalk( )
|
||||
do
|
||||
s:statusReport( f )
|
||||
|
||||
f:write( '\n' )
|
||||
end
|
||||
|
||||
Inotify.statusReport( f )
|
||||
|
||||
f:close( )
|
||||
end
|
||||
|
||||
--
|
||||
-- Public interface
|
||||
--
|
||||
return { write = write, getAlarm = getAlarm }
|
||||
end )( )
|
||||
|
||||
|
||||
--
|
||||
-- Lets userscripts make their own alarms.
|
||||
--
|
||||
local UserAlarms = ( function
|
||||
( )
|
||||
local alarms = { }
|
||||
|
||||
--
|
||||
-- Calls the user function at timestamp.
|
||||
--
|
||||
local function alarm
|
||||
(
|
||||
timestamp,
|
||||
func,
|
||||
extra
|
||||
)
|
||||
local idx
|
||||
|
||||
for k, v in ipairs( alarms )
|
||||
do
|
||||
if timestamp < v.timestamp
|
||||
then
|
||||
idx = k
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local a =
|
||||
{
|
||||
timestamp = timestamp,
|
||||
func = func,
|
||||
extra = extra
|
||||
}
|
||||
|
||||
if idx
|
||||
then
|
||||
table.insert( alarms, idx, a )
|
||||
else
|
||||
table.insert( alarms, a )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieves the soonest alarm.
|
||||
--
|
||||
local function getAlarm
|
||||
( )
|
||||
if #alarms == 0
|
||||
then
|
||||
return false
|
||||
else
|
||||
return alarms[1].timestamp
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Calls user alarms.
|
||||
--
|
||||
local function invoke
|
||||
(
|
||||
timestamp
|
||||
)
|
||||
while #alarms > 0
|
||||
and alarms[ 1 ].timestamp <= timestamp
|
||||
do
|
||||
alarms[ 1 ].func( alarms[ 1 ].timestamp, alarms[ 1 ].extra )
|
||||
table.remove( alarms, 1 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Public interface
|
||||
--
|
||||
return {
|
||||
alarm = alarm,
|
||||
getAlarm = getAlarm,
|
||||
invoke = invoke
|
||||
}
|
||||
|
||||
end )( )
|
||||
|
||||
|
||||
--============================================================================
|
||||
-- Mantle core interface. These functions are called from core.
|
||||
--============================================================================
|
||||
|
@ -283,7 +92,8 @@ end )( )
|
|||
-- 'run' ... normal operation
|
||||
-- 'fade' ... waits for remaining processes
|
||||
--
|
||||
local lsyncdStatus = 'init'
|
||||
lsyncdStatus = 'init'
|
||||
|
||||
|
||||
--
|
||||
-- The mantle cores interface
|
||||
|
@ -305,7 +115,7 @@ function mci.callError
|
|||
(
|
||||
message
|
||||
)
|
||||
core.log( 'Error', 'in Lua: ', message )
|
||||
log( 'Error', 'in Lua: ', message )
|
||||
|
||||
-- prints backtrace
|
||||
local level = 2
|
||||
|
@ -317,8 +127,7 @@ function mci.callError
|
|||
if not info then terminate( -1 ) end
|
||||
|
||||
log(
|
||||
'Error',
|
||||
'Backtrace ',
|
||||
'Error', 'Backtrace ',
|
||||
level - 1, ' :',
|
||||
info.short_src, ':',
|
||||
info.currentline
|
||||
|
@ -364,7 +173,8 @@ end
|
|||
-- * received filesystem events.
|
||||
-- * received a HUP, TERM or INT signal.
|
||||
--
|
||||
function mci.cycle(
|
||||
function mci.cycle
|
||||
(
|
||||
timestamp -- the current kernel time (in jiffies)
|
||||
)
|
||||
log( 'Function', 'cycle( ', timestamp, ' )' )
|
||||
|
@ -1019,27 +829,27 @@ alarm = UserAlarms.alarm
|
|||
|
||||
--
|
||||
-- Comfort routine, also for user.
|
||||
-- Returns true if 'String' starts with 'Start'
|
||||
-- Returns true if 'str' starts with 'Start'
|
||||
--
|
||||
function string.starts
|
||||
(
|
||||
String,
|
||||
str,
|
||||
Start
|
||||
)
|
||||
return string.sub( String, 1, #Start ) == Start
|
||||
return string.sub( str, 1, #Start ) == Start
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Comfort routine, also for user.
|
||||
-- Returns true if 'String' ends with 'End'
|
||||
-- Returns true if 'str' ends with 'End'
|
||||
--
|
||||
function string.ends
|
||||
(
|
||||
String,
|
||||
str,
|
||||
End
|
||||
)
|
||||
return End == '' or string.sub( String, -#End ) == End
|
||||
return End == '' or string.sub( str, -#End ) == End
|
||||
end
|
||||
|
||||
|
||||
|
@ -1080,4 +890,3 @@ function settings
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- status.lua Live (Mirror) Syncing Demon
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Writes a status report file at most every 'statusintervall' seconds.
|
47
mantle/string.lua
Normal file
47
mantle/string.lua
Normal file
|
@ -0,0 +1,47 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- String comfort routines, also exported to user scripts.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Comfort routines, also for user.
|
||||
-- Returns true if 'str' starts with 'start'
|
||||
--
|
||||
function string.starts
|
||||
(
|
||||
str,
|
||||
start
|
||||
)
|
||||
return string.sub( str, 1, #start ) == start
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Comfort routine, also for user.
|
||||
-- Returns true if 'str' ends with 'ends'
|
||||
--
|
||||
function string.ends
|
||||
(
|
||||
str,
|
||||
ends
|
||||
)
|
||||
return ends == '' or string.sub( str, -#ends ) == ends
|
||||
end
|
||||
|
217
mantle/user.lua
Normal file
217
mantle/user.lua
Normal file
|
@ -0,0 +1,217 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- user.lua
|
||||
--
|
||||
--
|
||||
-- Lsyncd user script interface
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Main utility to create new observations.
|
||||
--
|
||||
-- Returns an Inlet to that sync.
|
||||
--
|
||||
function sync
|
||||
(
|
||||
opts
|
||||
)
|
||||
if lsyncdStatus ~= 'init'
|
||||
then
|
||||
error( 'Sync can only be created during initialization.', 2 )
|
||||
end
|
||||
|
||||
return SyncMaster.add( opts ).inlet
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Spawns a new child process.
|
||||
--
|
||||
function spawn
|
||||
(
|
||||
agent, -- the reason why a process is spawned.
|
||||
-- a delay or delay list for a sync
|
||||
-- it will mark the related files as blocked.
|
||||
binary, -- binary to call
|
||||
... -- arguments
|
||||
)
|
||||
if agent == nil
|
||||
or type( agent ) ~= 'table'
|
||||
then
|
||||
error( 'spawning with an invalid agent', 2 )
|
||||
end
|
||||
|
||||
if lsyncdStatus == 'fade'
|
||||
then
|
||||
log( 'Normal', 'ignored process spawning while fading' )
|
||||
return
|
||||
end
|
||||
|
||||
if type( binary ) ~= 'string'
|
||||
then
|
||||
error( 'calling spawn(agent, binary, ...): binary is not a string', 2 )
|
||||
end
|
||||
|
||||
local dol = InletFactory.getDelayOrList( agent )
|
||||
|
||||
if not dol
|
||||
then
|
||||
error( 'spawning with an unknown agent', 2 )
|
||||
end
|
||||
|
||||
--
|
||||
-- checks if a spawn is called on an already active event
|
||||
--
|
||||
if dol.status
|
||||
then
|
||||
-- is an event
|
||||
|
||||
if dol.status ~= 'wait'
|
||||
then
|
||||
error( 'spawn() called on an non-waiting event', 2 )
|
||||
end
|
||||
else
|
||||
-- is a list
|
||||
for _, d in ipairs( dol )
|
||||
do
|
||||
if d.status ~= 'wait'
|
||||
and d.status ~= 'block'
|
||||
then
|
||||
error( 'spawn() called on an non-waiting event list', 2 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- tries to spawn the process
|
||||
--
|
||||
local pid = core.exec( binary, ... )
|
||||
|
||||
if pid and pid > 0
|
||||
then
|
||||
processCount = processCount + 1
|
||||
|
||||
if uSettings.maxProcesses
|
||||
and processCount > uSettings.maxProcesses
|
||||
then
|
||||
error( 'Spawned too much processes!' )
|
||||
end
|
||||
|
||||
local sync = InletFactory.getSync( agent )
|
||||
|
||||
-- delay or list
|
||||
if dol.status
|
||||
then
|
||||
-- is a delay
|
||||
dol:setActive( )
|
||||
|
||||
sync.processes[ pid ] = dol
|
||||
else
|
||||
-- is a list
|
||||
for _, d in ipairs( dol )
|
||||
do
|
||||
d:setActive( )
|
||||
end
|
||||
|
||||
sync.processes[ pid ] = dol
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Spawns a child process using the default shell.
|
||||
--
|
||||
function spawnShell
|
||||
(
|
||||
agent, -- the delay(list) to spawn the command for
|
||||
command, -- the shell command
|
||||
... -- additonal arguments
|
||||
)
|
||||
return spawn( agent, '/bin/sh', '-c', command, '/bin/sh', ... )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Observes a filedescriptor.
|
||||
--
|
||||
function observefd
|
||||
(
|
||||
fd, -- file descriptor
|
||||
ready, -- called when fd is ready to be read
|
||||
writey -- called when fd is ready to be written
|
||||
)
|
||||
return core.observe_fd( fd, ready, writey )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Stops observeing a filedescriptor.
|
||||
--
|
||||
function nonobservefd
|
||||
(
|
||||
fd -- file descriptor
|
||||
)
|
||||
return core.nonobserve_fd( fd )
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Calls func at timestamp.
|
||||
--
|
||||
-- Use now() to receive current timestamp
|
||||
-- add seconds with '+' to it
|
||||
--
|
||||
alarm = UserAlarms.alarm
|
||||
|
||||
|
||||
--
|
||||
-- The settings call
|
||||
--
|
||||
function settings
|
||||
(
|
||||
a1 -- a string for getting a setting
|
||||
-- or a table of key/value pairs to set these settings
|
||||
)
|
||||
|
||||
-- if a1 is a string this is a get operation
|
||||
if type( a1 ) == 'string'
|
||||
then
|
||||
return uSettings[ a1 ]
|
||||
end
|
||||
|
||||
-- if its a table it sets all the value of the bale
|
||||
for k, v in pairs( a1 )
|
||||
do
|
||||
if type( k ) ~= 'number'
|
||||
then
|
||||
if not settingsCheckgauge[ k ]
|
||||
then
|
||||
error( 'setting "'..k..'" unknown.', 2 )
|
||||
end
|
||||
|
||||
uSettings[ k ] = v
|
||||
else
|
||||
if not settingsCheckgauge[ v ]
|
||||
then
|
||||
error( 'setting "'..v..'" unknown.', 2 )
|
||||
end
|
||||
|
||||
uSettings[ v ] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
101
mantle/useralarm.lua
Normal file
101
mantle/useralarm.lua
Normal file
|
@ -0,0 +1,101 @@
|
|||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
-- lsyncd.lua Live (Mirror) Syncing Demon
|
||||
--
|
||||
--
|
||||
-- Lets userscripts make their own alarms.
|
||||
--
|
||||
--
|
||||
-- This code assumes your editor is at least 100 chars wide.
|
||||
--
|
||||
-- License: GPLv2 (see COPYING) or any later version
|
||||
-- Authors: Axel Kittenberger <axkibe@gmail.com>
|
||||
--
|
||||
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
if mantle
|
||||
then
|
||||
print( 'Error, Lsyncd mantle already loaded' )
|
||||
os.exit( -1 )
|
||||
end
|
||||
|
||||
|
||||
local alarms = { }
|
||||
|
||||
--
|
||||
-- Calls the user function at timestamp.
|
||||
--
|
||||
local function alarm
|
||||
(
|
||||
timestamp,
|
||||
func,
|
||||
extra
|
||||
)
|
||||
local idx
|
||||
|
||||
for k, v in ipairs( alarms )
|
||||
do
|
||||
if timestamp < v.timestamp
|
||||
then
|
||||
idx = k
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
local a =
|
||||
{
|
||||
timestamp = timestamp,
|
||||
func = func,
|
||||
extra = extra
|
||||
}
|
||||
|
||||
if idx
|
||||
then
|
||||
table.insert( alarms, idx, a )
|
||||
else
|
||||
table.insert( alarms, a )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Retrieves the soonest alarm.
|
||||
--
|
||||
local function getAlarm
|
||||
( )
|
||||
if #alarms == 0
|
||||
then
|
||||
return false
|
||||
else
|
||||
return alarms[1].timestamp
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Calls user alarms.
|
||||
--
|
||||
local function invoke
|
||||
(
|
||||
timestamp
|
||||
)
|
||||
while #alarms > 0
|
||||
and alarms[ 1 ].timestamp <= timestamp
|
||||
do
|
||||
alarms[ 1 ].func( alarms[ 1 ].timestamp, alarms[ 1 ].extra )
|
||||
table.remove( alarms, 1 )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Exported interface.
|
||||
--
|
||||
UserAlarms =
|
||||
{
|
||||
alarm = alarm,
|
||||
getAlarm = getAlarm,
|
||||
invoke = invoke
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user