mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-12-12 14:17:47 +00:00
This commit is contained in:
parent
201d78757e
commit
b3dde93eaa
124
lsyncd.c
124
lsyncd.c
@ -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) {
|
||||
|
126
lsyncd.lua
126
lsyncd.lua
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user