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 <string.h>
#include <syslog.h>
#include <math.h>
#include <time.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
extern char _binary_luac_out_start;
@ -149,7 +150,7 @@ sig_child(int sig)
/* nothing */
}
/**
* predeclerations -- see belorw.
* predeclerations -- see below
*/
static void * s_calloc(size_t nmemb, size_t size);
static void * s_malloc(size_t size);
@ -160,22 +161,6 @@ static char * s_strdup(const char *src);
* 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
*/
@ -184,7 +169,6 @@ struct logcat {
int priority;
};
/**
* A table of all enabled logging categories.
* 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 message the log message
*/
#define logstring(cat, message) \
{int p; if ((p = check_logcat(cat)) >= settings.log_level) \
{logstring0(p, cat, message);}}
static void
logstring0(int priority, const char *cat, const char *message)
{
@ -327,6 +316,36 @@ logstring0(int priority, const char *cat, const char *message)
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
****************************************************************************/
@ -396,6 +415,8 @@ s_strdup(const char *src)
*
****************************************************************************/
static int l_stackdump(lua_State* L);
/**
* Adds an inotify watch
*
@ -431,12 +452,34 @@ l_log(lua_State *L)
cat = luaL_checkstring(L, 1);
priority = check_logcat(cat);
/* skips filtered messages */
if (priority < 0) {
if (priority < settings.log_level) {
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 */
lua_concat(L, lua_gettop(L) - 1);
@ -876,23 +919,7 @@ static const luaL_reg lsyncdlib[] = {
* 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.
@ -1005,7 +1032,7 @@ void handle_event(lua_State *L, struct inotify_event *event) {
case DELETE : lua_pushstring(L, "Delete"); break;
case MOVE : lua_pushstring(L, "Move"); break;
default :
logstring("Inotify", "Internal: unknown event in handle_event()");
logstring("Error", "Internal: unknown event in handle_event()");
exit(-1); // ERRNO
}
lua_pushnumber(L, event->wd);
@ -1051,7 +1078,7 @@ masterloop(lua_State *L)
alarm_time = (clock_t) luaL_checkinteger(L, -1);
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
* read from inotify_fd and jump directly to its handling */
logstring("Masterloop", "immediately handling delays.");
@ -1067,12 +1094,13 @@ masterloop(lua_State *L)
sigemptyset(&sigset);
if (have_alarm) {
logstring("Masterloop", "going into timed select.");
tv.tv_sec = (alarm_time - now) / clocks_per_sec;
tv.tv_nsec = (alarm_time - now) *
1000000000 / clocks_per_sec % 1000000000;
double d = ((double)(alarm_time - now)) / clocks_per_sec;
tv.tv_sec = d;
tv.tv_nsec = ((d - (long) d)) * 1000000000.0;
printlogf(L, "Masterloop",
"going into select (timeout %f seconds)", d);
} 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
* on zero the timemout occured. */
@ -1218,13 +1246,17 @@ main(int argc, char *argv[])
}
}
}
/* TODO check lua version */
luaL_openlibs(L);
luaL_register(L, "lsyncd", lsyncdlib);
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 */
if (argp < argc && !strcmp(argv[argp], "--runner")) {
if (argp + 1 < argc) {

View File

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