mirror of
https://github.com/octoleo/lsyncd.git
synced 2024-06-07 19:00:51 +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 <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) {
|
||||||
|
|
122
lsyncd.lua
122
lsyncd.lua
|
@ -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
|
-- TODO
|
||||||
local inlet = {
|
local function control(set_origin, set_delay)
|
||||||
[hk] = {
|
origin = set_origin
|
||||||
origin = true,
|
delay = set_delay
|
||||||
delay = true,
|
end
|
||||||
},
|
|
||||||
|
|
||||||
config = function(self)
|
-----
|
||||||
return self[hk].origin.config
|
-- TODO
|
||||||
end,
|
local function get_event()
|
||||||
|
|
||||||
nextevent = function(self)
|
|
||||||
local h = self[hk]
|
|
||||||
return {
|
return {
|
||||||
spath = h.origin.source .. h.delay.pathname,
|
spath = origin.source .. delay.pathname,
|
||||||
tpath = h.origin.targetident .. h.delay.pathname,
|
tpath = origin.targetident .. delay.pathname,
|
||||||
ename = h.delay.ename
|
ename = delay.ename
|
||||||
}
|
}
|
||||||
end,
|
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
|
-- 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user