This commit is contained in:
Axel Kittenberger 2010-11-04 13:43:57 +00:00
parent 201d78757e
commit b3dde93eaa
2 changed files with 161 additions and 89 deletions

124
lsyncd.c
View File

@ -32,6 +32,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
#include <math.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
@ -64,7 +65,7 @@ enum event_type {
}; };
/** /**
* The Lua part of lsyncd. * The Lua part of lsyncd if compiled into the binary.
*/ */
#ifndef LSYNCD_DEFAULT_RUNNER_FILE #ifndef LSYNCD_DEFAULT_RUNNER_FILE
extern char _binary_luac_out_start; extern char _binary_luac_out_start;
@ -149,7 +150,7 @@ sig_child(int sig)
/* nothing */ /* nothing */
} }
/** /**
* predeclerations -- see belorw. * predeclerations -- see below
*/ */
static void * s_calloc(size_t nmemb, size_t size); static void * s_calloc(size_t nmemb, size_t size);
static void * s_malloc(size_t size); static void * s_malloc(size_t size);
@ -160,22 +161,6 @@ static char * s_strdup(const char *src);
* Logging * Logging
****************************************************************************/ ****************************************************************************/
/* core logs with CORE flag */
#define logstring(cat, message) \
{int p; if ((p = check_logcat(cat)) >= settings.log_level) \
{logstring0(p, cat, message); }}
static void
printlogf0(lua_State *L,
int priority,
const char *cat,
const char *fmt,
...)
__attribute__((format(printf, 4, 5)));
#define printlogf(L, cat, ...) \
{int p; if ((p = check_logcat(cat)) >= settings.log_level) \
{printlogf0(L, p, cat, __VA_ARGS__);}}
/** /**
* A logging category * A logging category
*/ */
@ -184,7 +169,6 @@ struct logcat {
int priority; int priority;
}; };
/** /**
* A table of all enabled logging categories. * A table of all enabled logging categories.
* Sorted by first letter to have to do less comparisons; * Sorted by first letter to have to do less comparisons;
@ -271,6 +255,11 @@ add_logcat(const char *name, int priority)
* @param cat the category * @param cat the category
* @param message the log message * @param message the log message
*/ */
#define logstring(cat, message) \
{int p; if ((p = check_logcat(cat)) >= settings.log_level) \
{logstring0(p, cat, message);}}
static void static void
logstring0(int priority, const char *cat, const char *message) logstring0(int priority, const char *cat, const char *message)
{ {
@ -327,6 +316,36 @@ logstring0(int priority, const char *cat, const char *message)
return; return;
} }
/**
* Let the core print logmessage comfortably.
* This uses the lua_State for it easy string buffers only.
*/
#define printlogf(L, cat, ...) \
{int p; if ((p = check_logcat(cat)) >= settings.log_level) \
{printlogf0(L, p, cat, __VA_ARGS__);}}
static void
printlogf0(lua_State *L,
int priority,
const char *cat,
const char *fmt,
...)
__attribute__((format(printf, 4, 5)));
static void
printlogf0(lua_State *L,
int priority,
const char *cat,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lua_pushvfstring(L, fmt, ap);
va_end(ap);
logstring0(priority, cat, luaL_checkstring(L, -1));
lua_pop(L, 1);
return;
}
/***************************************************************************** /*****************************************************************************
* Simple memory management * Simple memory management
****************************************************************************/ ****************************************************************************/
@ -396,6 +415,8 @@ s_strdup(const char *src)
* *
****************************************************************************/ ****************************************************************************/
static int l_stackdump(lua_State* L);
/** /**
* Adds an inotify watch * Adds an inotify watch
* *
@ -431,12 +452,34 @@ l_log(lua_State *L)
cat = luaL_checkstring(L, 1); cat = luaL_checkstring(L, 1);
priority = check_logcat(cat); priority = check_logcat(cat);
/* skips filtered messages */ /* skips filtered messages */
if (priority < 0) { if (priority < settings.log_level) {
return 0; return 0;
} }
{
// replace non string values
int i;
int top = lua_gettop(L);
for (i = 1; i <= top; i++) {
int t = lua_type(L, i);
switch (t) {
case LUA_TTABLE:
lua_pushfstring(L, "(Table: %p)", lua_topointer(L, i));
lua_replace(L, i);
break;
case LUA_TBOOLEAN:
if (lua_toboolean(L, i)) {
lua_pushstring(L, "(true)");
} else {
lua_pushstring(L, "(false)");
}
lua_replace(L, i);
break;
}
}
}
/* concates if there is more than one string parameter */ /* concates if there is more than one string parameter */
lua_concat(L, lua_gettop(L) - 1); lua_concat(L, lua_gettop(L) - 1);
@ -876,23 +919,7 @@ static const luaL_reg lsyncdlib[] = {
* Lsyncd Core * Lsyncd Core
****************************************************************************/ ****************************************************************************/
/**
* Let the core print logmessage comfortably.
*/
static void
printlogf0(lua_State *L,
int priority,
const char *cat,
const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
lua_pushvfstring(L, fmt, ap);
va_end(ap);
logstring0(priority, cat, luaL_checkstring(L, -1));
lua_pop(L, 1);
return;
}
/** /**
* Buffer for MOVE_FROM events. * Buffer for MOVE_FROM events.
@ -1005,7 +1032,7 @@ void handle_event(lua_State *L, struct inotify_event *event) {
case DELETE : lua_pushstring(L, "Delete"); break; case DELETE : lua_pushstring(L, "Delete"); break;
case MOVE : lua_pushstring(L, "Move"); break; case MOVE : lua_pushstring(L, "Move"); break;
default : default :
logstring("Inotify", "Internal: unknown event in handle_event()"); logstring("Error", "Internal: unknown event in handle_event()");
exit(-1); // ERRNO exit(-1); // ERRNO
} }
lua_pushnumber(L, event->wd); lua_pushnumber(L, event->wd);
@ -1051,7 +1078,7 @@ masterloop(lua_State *L)
alarm_time = (clock_t) luaL_checkinteger(L, -1); alarm_time = (clock_t) luaL_checkinteger(L, -1);
lua_pop(L, 3); lua_pop(L, 3);
if (have_alarm && time_before(alarm_time, now)) { if (have_alarm && time_before_eq(alarm_time, now)) {
/* there is a delay that wants to be handled already thus do not /* there is a delay that wants to be handled already thus do not
* read from inotify_fd and jump directly to its handling */ * read from inotify_fd and jump directly to its handling */
logstring("Masterloop", "immediately handling delays."); logstring("Masterloop", "immediately handling delays.");
@ -1067,12 +1094,13 @@ masterloop(lua_State *L)
sigemptyset(&sigset); sigemptyset(&sigset);
if (have_alarm) { if (have_alarm) {
logstring("Masterloop", "going into timed select."); double d = ((double)(alarm_time - now)) / clocks_per_sec;
tv.tv_sec = (alarm_time - now) / clocks_per_sec; tv.tv_sec = d;
tv.tv_nsec = (alarm_time - now) * tv.tv_nsec = ((d - (long) d)) * 1000000000.0;
1000000000 / clocks_per_sec % 1000000000; printlogf(L, "Masterloop",
"going into select (timeout %f seconds)", d);
} else { } else {
logstring("Masterloop", "going into blocking select."); logstring("Masterloop", "going into select (no timeout).");
} }
/* if select returns a positive number there is data on inotify /* if select returns a positive number there is data on inotify
* on zero the timemout occured. */ * on zero the timemout occured. */
@ -1219,12 +1247,16 @@ main(int argc, char *argv[])
} }
} }
/* TODO check lua version */ /* TODO check lua version */
luaL_openlibs(L); luaL_openlibs(L);
luaL_register(L, "lsyncd", lsyncdlib); luaL_register(L, "lsyncd", lsyncdlib);
lua_setglobal(L, "lysncd"); lua_setglobal(L, "lysncd");
if (check_logcat("Debug") >= settings.log_level) {
/* printlogf doesnt support %ld :-( */
printf("kernels clocks_per_sec=%ld\n", clocks_per_sec);
}
/* checks if the user overrode default runner file */ /* checks if the user overrode default runner file */
if (argp < argc && !strcmp(argv[argp], "--runner")) { if (argp < argc && !strcmp(argv[argp], "--runner")) {
if (argp + 1 < argc) { if (argp + 1 < argc) {

View File

@ -16,9 +16,9 @@
-- --
if lsyncd_version then if lsyncd_version then
-- checks if the runner is being loaded twice -- checks if the runner is being loaded twice
io.stderr:write( lsyncd.log("Error",
"You cannot use the lsyncd runner as configuration file!\n") "You cannot use the lsyncd runner as configuration file!")
os.exit(-1) -- ERRNO lsyncd.terminate(-1) -- ERRNO
end end
lsyncd_version = "2.0beta1" lsyncd_version = "2.0beta1"
@ -191,6 +191,11 @@ end
----- -----
-- Holds information about a delayed event for one origin/target. -- Holds information about a delayed event for one origin/target.
-- --
-- valid stati are:
-- delay
-- active
-- TODO
--
local Delay = (function() local Delay = (function()
----- -----
-- Creates a new delay. -- Creates a new delay.
@ -201,6 +206,7 @@ local Delay = (function()
ename = ename, ename = ename,
alarm = alarm, alarm = alarm,
pathname = pathname, pathname = pathname,
status = "delay",
} }
return o return o
end end
@ -234,8 +240,8 @@ end)()
----- -----
-- Puts an action on the delay stack. -- Puts an action on the delay stack.
-- --
function Origin:delay(origin, ename, time, pathname, pathname2) function Origin.delay(origin, ename, time, pathname, pathname2)
log("Debug", "delay ", ename, " ", pathname) log("Function", "delay(", origin, ", ", ename, ", ", pathname, ")")
local o = origin local o = origin
local delays = o.delays local delays = o.delays
local delayname = o.delayname local delayname = o.delayname
@ -419,6 +425,7 @@ local Inotifies = (function()
-- or the relative path to root for recurse -- or the relative path to root for recurse
-- --
local function add(root, origin, recurse) local function add(root, origin, recurse)
log("Function", "Inotifies.add(", root, ", ", origin, ", ", recurse, ")")
-- register watch and receive watch descriptor -- register watch and receive watch descriptor
local dir local dir
if type(recurse) == "string" then if type(recurse) == "string" then
@ -493,7 +500,7 @@ local Inotifies = (function()
pathname2 = inotify.path..filename2 pathname2 = inotify.path..filename2
end end
Origin.delay(inotify.origin, ename, time, pathname, pathname2) Origin.delay(inotify.origin, ename, time, pathname, pathname2)
-- add subdirs for new directories -- adds subdirs for new directories
if inotify.recurse and isdir then if inotify.recurse and isdir then
if ename == "Create" then if ename == "Create" then
add(inotify.root, inotify.origin, add(inotify.root, inotify.origin,
@ -526,7 +533,12 @@ local Inotifies = (function()
end end
-- public interface -- public interface
return { add = add, size = size, status_report = status_report } return {
add = add,
size = size,
event = event,
status_report = status_report
}
end)() end)()
--============================================================================ --============================================================================
@ -574,52 +586,59 @@ function lsyncd_collect_process(pid, exitcode)
origin.processes[pid] = nil origin.processes[pid] = nil
end end
------ -----
-- Hidden key for lsyncd.lua internal variables not ment for -- User interface to grap events
-- the user to see
-- --
local hk = {} -- inlet_control is the Luas runner part to control the interface
-- hidden from the user.
--
local Inlet, inlet_control = (function()
local origin = true
local delay = true
-----
-- TODO
local function control(set_origin, set_delay)
origin = set_origin
delay = set_delay
end
-----
-- TODO
local function get_event()
return {
spath = origin.source .. delay.pathname,
tpath = origin.targetident .. delay.pathname,
ename = delay.ename
}
end
------ ------
--- TODO -- TODO
local inlet = { local function get_config()
[hk] = { -- TODO give a readonly handler only.
origin = true, return origin.config
delay = true, end
},
config = function(self)
return self[hk].origin.config
end,
nextevent = function(self)
local h = self[hk]
return {
spath = h.origin.source .. h.delay.pathname,
tpath = h.origin.targetident .. h.delay.pathname,
ename = h.delay.ename
}
end,
}
-- public interface
return {get_event = get_event, get_config = get_config}, control
end)()
----- -----
-- TODO -- TODO
-- --
-- --
local function invoke_action(origin, delay) local function invoke_action(origin, delay)
local o = origin
local config = o.config
if delay.ename == "None" then if delay.ename == "None" then
-- a removed action -- a removed action
return return
end end
inlet[hk].origin = origin inlet_control(origin, delay)
inlet[hk].delay = delay local pid = origin.config.action(Inlet)
local pid = config.action(inlet)
if pid and pid > 0 then if pid and pid > 0 then
o.processes[pid] = delay delay.status = "active"
origin.processes[pid] = delay
end end
end end
@ -662,8 +681,27 @@ end
-- --
function lsyncd_help() function lsyncd_help()
io.stdout:write( io.stdout:write(
[[TODO this is a multiline [[
help USAGE:
run a config file:
lsyncd [OPTIONS] [CONFIG-FILE]
default rsync behaviour:
lsyncd [OPTIONS] -rsync [SOURCE] [TARGET1] [TARGET2] ...
OPTIONS:
-help Shows this
-log [Category] Turns logging on for debug categories.
-log all Logs everything
-log scarce Logs errors only
-runner FILE Loads lsyncds lua part from FILE
LICENSE:
GPLv2 or any later version.
SEE:
`man lsyncd` for further information.
]]) ]])
os.exit(-1) -- ERRNO os.exit(-1) -- ERRNO
end end
@ -705,7 +743,7 @@ function lsyncd_configure(args)
end end
if #nonopts == 0 then if #nonopts == 0 then
lsyncd_help() lsyncd_help(args[0])
elseif #nonopts == 1 then elseif #nonopts == 1 then
return nonopts[1] return nonopts[1]
else else
@ -762,7 +800,7 @@ function lsyncd_initialize()
have_startup = true have_startup = true
end end
-- adds the dir watch inclusively all subdirs -- adds the dir watch inclusively all subdirs
Inotifies.add(o.source, "", true) Inotifies.add(o.source, o, true)
end end
-- from now on use logging as configured instead of stdout/err. -- from now on use logging as configured instead of stdout/err.
@ -798,6 +836,7 @@ function lsyncd_get_alarm()
local have_alarm = false local have_alarm = false
local alarm = 0 local alarm = 0
for _, o in Origins.iwalk() do for _, o in Origins.iwalk() do
-- TODO better handling of stati.
if o.delays[1] and if o.delays[1] and
o.processes:size() < o.config.max_processes then o.processes:size() < o.config.max_processes then
if have_alarm then if have_alarm then
@ -808,6 +847,7 @@ function lsyncd_get_alarm()
end end
end end
end end
log("Debug", "lysncd_get_alarm returns: ", have_alarm, ", ", alarm)
return have_alarm, alarm return have_alarm, alarm
end end
@ -885,8 +925,8 @@ default = {
-- TODO desc -- TODO desc
-- --
action = function(inlet) action = function(inlet)
local event = inlet:nextevent() local event = inlet.get_event()
local func = inlet:config()[string.lower(event.ename)] local func = inlet.get_config()[string.lower(event.ename)]
if func then if func then
return func(event) return func(event)
else else