further structering mantle

This commit is contained in:
Axel Kittenberger 2018-03-19 08:50:29 +01:00
parent 5771779e28
commit 2f1a1967ab
6 changed files with 382 additions and 205 deletions

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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
}