diff --git a/default.lua b/default.lua index e180fd7..f1172e2 100644 --- a/default.lua +++ b/default.lua @@ -38,6 +38,7 @@ default.checkgauge = { action = true, checkgauge = true, collect = true, + crontab = true, delay = true, exitcodes = true, init = true, diff --git a/lsyncd.c b/lsyncd.c index 31540f2..53cc128 100644 --- a/lsyncd.c +++ b/lsyncd.c @@ -1945,25 +1945,26 @@ l_nonobserve_fd( lua_State *L ) return 0; } - +static int l_jiffies_fromseconds(lua_State *L); /* | The Lsnycd's core library */ static const luaL_Reg lsyncdlib[] = -{ - { "configure", l_configure }, - { "exec", l_exec }, - { "log", l_log }, - { "now", l_now }, - { "kill", l_kill }, - { "get_free_port", l_free_port }, - { "nonobserve_fd", l_nonobserve_fd }, - { "observe_fd", l_observe_fd }, - { "readdir", l_readdir }, - { "realdir", l_realdir }, - { "stackdump", l_stackdump }, - { "terminate", l_terminate }, - { NULL, NULL } +{ + { "configure", l_configure }, + { "exec", l_exec }, + { "log", l_log }, + { "now", l_now }, + { "jiffies_from_seconds", l_jiffies_fromseconds}, + { "kill", l_kill }, + { "get_free_port", l_free_port }, + { "nonobserve_fd", l_nonobserve_fd }, + { "observe_fd", l_observe_fd }, + { "readdir", l_readdir }, + { "realdir", l_realdir }, + { "stackdump", l_stackdump }, + { "terminate", l_terminate }, + { NULL, NULL } }; @@ -2103,6 +2104,53 @@ l_jiffies_le(lua_State *L) return 1; } +/* +| Converts a jiffies to a number +*/ +static int +l_jiffies_tonumber(lua_State *L) +{ + clock_t a1 = ( *( clock_t * ) luaL_checkudata( L, 1, "Lsyncd.jiffies" ) ); + + lua_pushinteger( L, a1 * clocks_per_sec); + return 1; +} + +/* +| Converts a jiffies to a number +*/ +static int +l_jiffies_fromseconds(lua_State *L) +{ + lua_Integer a1 = luaL_checkinteger(L, 1); + + clock_t *r = (clock_t *) lua_newuserdata( L, sizeof( clock_t ) ); + luaL_getmetatable( L, "Lsyncd.jiffies" ); + lua_setmetatable( L, -2 ); + + *r = a1 * clocks_per_sec; + + return 1; +} + +/* +| Converts a jiffies to a number +*/ +static int +l_jiffies_index(lua_State *L) +{ + clock_t a1 = ( *( clock_t * ) luaL_checkudata( L, 1, "Lsyncd.jiffies" ) ); + const char *a2 = luaL_checkstring(L, 2); + + printf("in index %s %d\n", a2, a1); + + if (!strcmp(a2, "seconds")) { + lua_pushinteger( L, a1 / clocks_per_sec); + return 1; + } + return 0; +} + /* | Registers the Lsyncd's core library. @@ -2135,6 +2183,9 @@ register_lsyncd( lua_State *L ) lua_pushcfunction( L, l_jiffies_concat ); lua_setfield( L, mt, "__concat" ); + lua_pushcfunction( L, l_jiffies_index ); + lua_setfield( L, mt, "__index" ); + lua_pop( L, 1 ); // pop(mt) #ifdef WITH_INOTIFY diff --git a/lsyncd.lua b/lsyncd.lua index 5f1493a..019cea9 100644 --- a/lsyncd.lua +++ b/lsyncd.lua @@ -172,6 +172,18 @@ local Monitors -- local processCount = 0 +local crontab = nil + +local function loadCrontab() + local ok, mod = pcall(require, "lua-crontab") + if ok then + -- print update crontab + crontab = mod + return true + end + return false + +end -- -- All valid entries in a settings{} call. @@ -2835,6 +2847,26 @@ local Sync = ( function recurse( ) end + local function updateNextCronAlarm(self, timestamp) + if timestamp == nil then + timestamp = now() + end + + print(type(now())) + local nalarm = type(self.nextCronAlarm) == "userdata" and self.nextCronAlarm.seconds or nil + for i, c in ipairs(self.cron) do + local na = c:get_next_occurrence(timestamp.seconds) + print("na", timestamp.seconds, na) + if nalarm == nil or nalarm > na then + nalarm = na + end + end + print("calculated next cron:", nalarm) + if nalarm ~= nil then + self.nextCronAlarm = lsyncd.jiffies_from_seconds(nalarm) + end + end + -- -- Returns the soonest alarm for this Sync. -- @@ -2847,6 +2879,12 @@ local Sync = ( function return false end + local rv = false + + if self.cron ~= nil and self.nextCronAlarm == false then + updateNextCronAlarm(self) + end + -- first checks if more processes could be spawned if self.processes:size( ) < self.config.maxProcesses then @@ -2855,13 +2893,21 @@ local Sync = ( function do if d.status == 'wait' then - return d.alarm + if rv == false or d.alarm < rv then + rv = d.alarm + end end end end + if rv == false and self.nextCronAlarm ~= false then + rv = self.nextCronAlarm + elseif rv == true then + elseif self.nextCronAlarm ~= false and self.nextCronAlarm < rv then + rv = self.nextCronAlarm + end -- nothing to spawn - return false + return rv end -- @@ -2955,6 +3001,14 @@ local Sync = ( function return end + if self.nextCronAlarm ~= false and self.nextCronAlarm < timestamp then + -- time fo a full sync + log('Info', 'Crontab triggered full sync') + -- TODO + + updateNextCronAlarm(self, timestamp) + end + for _, d in self.delays:qpairs( ) do -- if reached the global limit return @@ -3149,6 +3203,8 @@ local Sync = ( function initDone = false, disabled = false, tunnelBlock = nil, + cron = nil, + nextCronAlarm = false, -- functions addBlanketDelay = addBlanketDelay, @@ -3234,6 +3290,34 @@ local Sync = ( function s.excludes:loadFile( config.excludeFrom ) end + if config.crontab and loadCrontab() == false then + error("Sync ", config.name, " uses a crontab, but lua-crontab dependency is not available") + elseif config.crontab then + local cdata = {} + for i, v in ipairs( config.crontab ) do + local ok, cd = pcall(crontab.make_raw_cron_data_from_string, v) + if ok then + print ('getter') + local props = crontab.make_cron_properties(cd) + local getter = crontab.make_next_occurrence_getter(props) + print(getter) + for k, v in pairs( getter ) do + print(k,v) + end + table.insert( cdata, getter ) + else + error("Crontab rule ", i, " is not valid: ", cd, " . Rule: ", v) + end + + end + -- local ok, cron = pcall(crontab.make_crontab, cdata) + if #cdata then + s.cron = cdata + else + error("Can't parse crontab data: "..cron, 2) + end + end + return s end