This commit is contained in:
Axel Kittenberger 2010-11-14 09:11:09 +00:00
parent 3482ce51ef
commit ae786f3d9b
3 changed files with 166 additions and 35 deletions

View File

@ -1,19 +1,23 @@
---- -----
-- User configuration file for lsyncd. -- User configuration file for lsyncd.
-- --
-- This example uses local bash commands to keep two local -- This example uses local bash commands to keep two local
-- directory trees in sync. -- directory trees in sync.
-- --
settings = { settings = {
statusFile = "/tmp/lsyncd.stat", logfile = "/tmp/lsyncd.log",
statusFile = "/tmp/lsyncd.stat",
statusIntervall = 1, statusIntervall = 1,
nodaemon = true,
} }
---- -----
-- for testing purposes. prefix can be used to slow commands down. -- for testing purposes. prefix can be used to slow commands down.
-- prefix = "sleep 5 && " -- prefix = "sleep 5 && "
--
prefix = "" prefix = ""
----
-----
-- for testing purposes. uses bash command to hold local dirs in sync. -- for testing purposes. uses bash command to hold local dirs in sync.
-- --
bash = { bash = {

146
lsyncd.c
View File

@ -126,7 +126,8 @@ static bool running = false;
/** /**
* Set to TERM or HUP in signal handler, when lsyncd should end or reset ASAP. * Set to TERM or HUP in signal handler, when lsyncd should end or reset ASAP.
*/ */
static volatile sig_atomic_t reset = 0; static volatile sig_atomic_t hup = 0;
static volatile sig_atomic_t term = 0;
/** /**
* The kernels clock ticks per second. * The kernels clock ticks per second.
@ -141,6 +142,24 @@ sig_child(int sig)
{ {
/* nothing */ /* nothing */
} }
/**
* signal handler
*/
void
sig_handler(int sig)
{
switch (sig) {
case SIGTERM:
term = 1;
return;
case SIGHUP:
hup = 1;
return;
}
}
/** /**
* predeclerations -- see below * predeclerations -- see below
*/ */
@ -297,7 +316,7 @@ logstring0(int priority, const char *cat, const char *message)
settings.log_file); settings.log_file);
exit(-1); // ERRNO exit(-1); // ERRNO
} }
fprintf(flog, "%s %s: %s", ct, cat, message); fprintf(flog, "%s %s: %s\n", ct, cat, message);
fclose(flog); fclose(flog);
} }
@ -873,7 +892,7 @@ l_subdirs (lua_State *L)
} }
lua_newtable(L); lua_newtable(L);
while (!reset) { while (!hup && !term) {
struct dirent *de = readdir(d); struct dirent *de = readdir(d);
bool isdir; bool isdir;
if (de == NULL) { if (de == NULL) {
@ -957,7 +976,7 @@ l_configure(lua_State *L)
* from this on log to configurated log end instead of * from this on log to configurated log end instead of
* stdout/stderr */ * stdout/stderr */
running = true; running = true;
if (!settings.nodaemon) { if (!settings.nodaemon && !is_daemon) {
if (!settings.log_file) { if (!settings.log_file) {
settings.log_syslog = true; settings.log_syslog = true;
} }
@ -1069,16 +1088,17 @@ handle_event(lua_State *L,
/* used to execute two events in case of unmatched MOVE_FROM buffer */ /* used to execute two events in case of unmatched MOVE_FROM buffer */
struct inotify_event *after_buf = NULL; struct inotify_event *after_buf = NULL;
if (reset) { if (hup || term) {
return; return;
} }
if (event && (IN_Q_OVERFLOW & event->mask)) { if (event && (IN_Q_OVERFLOW & event->mask)) {
/* and overflow happened, lets runner/user decide what to do. */ /* and overflow happened, tells the runner */
load_runner_func(L, "overflow"); load_runner_func(L, "overflow");
if (lua_pcall(L, 0, 0, -2)) { if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); lua_pop(L, 1);
hup = 1;
return; return;
} }
/* cancel on ignored or resetting */ /* cancel on ignored or resetting */
@ -1188,7 +1208,7 @@ masterloop(lua_State *L)
{ {
size_t readbuf_size = 2048; size_t readbuf_size = 2048;
char *readbuf = s_malloc(readbuf_size); char *readbuf = s_malloc(readbuf_size);
while(!reset) { while(true) {
bool have_alarm; bool have_alarm;
clock_t now = times(NULL); clock_t now = times(NULL);
clock_t alarm_time; clock_t alarm_time;
@ -1283,7 +1303,7 @@ masterloop(lua_State *L)
/* nothing more inotify */ /* nothing more inotify */
break; break;
} }
while (i < len && !reset) { while (i < len && !hup && !term) {
struct inotify_event *event = struct inotify_event *event =
(struct inotify_event *) &readbuf[i]; (struct inotify_event *) &readbuf[i];
handle_event(L, event); handle_event(L, event);
@ -1343,14 +1363,38 @@ masterloop(lua_State *L)
lua_pop(L, 1); lua_pop(L, 1);
} }
if (hup) {
load_runner_func(L, "hup");
if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO
}
lua_pop(L, 1);
hup = 0;
}
if (term == 1) {
load_runner_func(L, "term");
if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO
}
lua_pop(L, 1);
term = 2;
}
/* lets the runner do stuff every cycle, /* lets the runner do stuff every cycle,
* like starting new processes, writing the statusfile etc. */ * like starting new processes, writing the statusfile etc. */
load_runner_func(L, "cycle"); load_runner_func(L, "cycle");
lua_pushinteger(L, times(NULL)); lua_pushinteger(L, times(NULL));
if (lua_pcall(L, 1, 0, -3)) { if (lua_pcall(L, 1, 1, -3)) {
exit(-1); // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); if (!lua_toboolean(L, -1)) {
/* cycle told core to break mainloop */
free(readbuf);
lua_pop(L, 2);
return;
}
lua_pop(L, 2);
} }
} }
@ -1358,7 +1402,7 @@ masterloop(lua_State *L)
* Main * Main
*/ */
int int
main(int argc, char *argv[]) main1(int argc, char *argv[])
{ {
/* the Lua interpreter */ /* the Lua interpreter */
lua_State* L; lua_State* L;
@ -1369,9 +1413,6 @@ main(int argc, char *argv[])
int argp = 1; int argp = 1;
/* kernel parameters */
clocks_per_sec = sysconf(_SC_CLK_TCK);
/* load Lua */ /* load Lua */
L = lua_open(); L = lua_open();
luaL_openlibs(L); luaL_openlibs(L);
@ -1383,11 +1424,11 @@ main(int argc, char *argv[])
version = luaL_checkstring(L, -1); version = luaL_checkstring(L, -1);
if (sscanf(version, "Lua %d.%d", &major, &minor) != 2) { if (sscanf(version, "Lua %d.%d", &major, &minor) != 2) {
fprintf(stderr, "cannot parse lua library version!\n"); fprintf(stderr, "cannot parse lua library version!\n");
return -1; // ERRNO exit(-1); // ERRNO
} }
if ((major < 5) || (major == 5 && minor < 1)) { if ((major < 5) || (major == 5 && minor < 1)) {
fprintf(stderr, "lua library is too old. Need 5.1 at least"); fprintf(stderr, "lua library is too old. Need 5.1 at least");
return -1; // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -1407,7 +1448,7 @@ main(int argc, char *argv[])
if (!add_logcat(argv[i], LOG_NOTICE)) { if (!add_logcat(argv[i], LOG_NOTICE)) {
printlogf(L, "Error", "'%s' is not a valid logging category", printlogf(L, "Error", "'%s' is not a valid logging category",
argv[i]); argv[i]);
return -1; // ERRNO exit(-1); // ERRNO
} }
} }
} }
@ -1452,14 +1493,14 @@ main(int argc, char *argv[])
printlogf(L, "Error", "Maybe specify another place?"); printlogf(L, "Error", "Maybe specify another place?");
printlogf(L, "Error", printlogf(L, "Error",
"%s --runner RUNNER_FILE CONFIG_FILE", argv[0]); "%s --runner RUNNER_FILE CONFIG_FILE", argv[0]);
return -1; // ERRNO exit(-1); // ERRNO
} }
/* loads the runner file */ /* loads the runner file */
if (luaL_loadfile(L, lsyncd_runner_file)) { if (luaL_loadfile(L, lsyncd_runner_file)) {
printlogf(L, "Error", printlogf(L, "Error",
"error loading '%s': %s", "error loading '%s': %s",
lsyncd_runner_file, lua_tostring(L, -1)); lsyncd_runner_file, lua_tostring(L, -1));
return -1; // ERRNO exit(-1); // ERRNO
} }
} else { } else {
#ifndef LSYNCD_DEFAULT_RUNNER_FILE #ifndef LSYNCD_DEFAULT_RUNNER_FILE
@ -1470,13 +1511,13 @@ main(int argc, char *argv[])
printlogf(L, "Error", printlogf(L, "Error",
"error loading precompiled lsyncd.lua runner: %s", "error loading precompiled lsyncd.lua runner: %s",
lua_tostring(L, -1)); lua_tostring(L, -1));
return -1; // ERRNO exit(-1); // ERRNO
} }
#else #else
/* this should never be possible, security code nevertheless */ /* this should never be possible, security code nevertheless */
logstring("Error", logstring("Error",
"Internal fail: lsyncd_runner is NULL with non-static runner"); "Internal fail: lsyncd_runner is NULL with non-static runner");
return -1; // ERRNO exit(-1); // ERRNO
#endif #endif
} }
@ -1488,7 +1529,7 @@ main(int argc, char *argv[])
"error preparing '%s': %s", "error preparing '%s': %s",
lsyncd_runner_file ? lsyncd_runner_file : "internal runner", lsyncd_runner_file ? lsyncd_runner_file : "internal runner",
lua_tostring(L, -1)); lua_tostring(L, -1));
return -1; // ERRNO exit(-1); // ERRNO
} }
lua_pushlightuserdata(L, (void *)&runner); lua_pushlightuserdata(L, (void *)&runner);
/* switches the value (result of preparing) and the key &runner */ /* switches the value (result of preparing) and the key &runner */
@ -1518,7 +1559,7 @@ main(int argc, char *argv[])
"Version mismatch '%s' is '%s', but core is '%s'", "Version mismatch '%s' is '%s', but core is '%s'",
lsyncd_runner_file ? lsyncd_runner_file : "internal runner", lsyncd_runner_file ? lsyncd_runner_file : "internal runner",
lversion, PACKAGE_VERSION); lversion, PACKAGE_VERSION);
return -1; // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); lua_pop(L, 1);
} }
@ -1533,7 +1574,7 @@ main(int argc, char *argv[])
exit(-1); // ERRNO exit(-1); // ERRNO
} }
lua_pop(L, 1); lua_pop(L, 1);
return -1; // ERRNO exit(-1); // ERRNO
} }
} }
} }
@ -1567,7 +1608,7 @@ main(int argc, char *argv[])
printlogf(L, "Error", printlogf(L, "Error",
"Cannot find config file at '%s'.", "Cannot find config file at '%s'.",
lsyncd_config_file); lsyncd_config_file);
return -1; // ERRNO exit(-1); // ERRNO
} }
/* loads and executes the config file */ /* loads and executes the config file */
@ -1575,13 +1616,13 @@ main(int argc, char *argv[])
printlogf(L, "Error", printlogf(L, "Error",
"error loading %s: %s", "error loading %s: %s",
lsyncd_config_file, lua_tostring(L, -1)); lsyncd_config_file, lua_tostring(L, -1));
return -1; // ERRNO exit(-1); // ERRNO
} }
if (lua_pcall(L, 0, LUA_MULTRET, 0)) { if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
printlogf(L, "Error", printlogf(L, "Error",
"error preparing %s: %s", "error preparing %s: %s",
lsyncd_config_file, lua_tostring(L, -1)); lsyncd_config_file, lua_tostring(L, -1));
return -1; // ERRNO exit(-1); // ERRNO
} }
} }
@ -1591,7 +1632,7 @@ main(int argc, char *argv[])
printlogf(L, "Error", printlogf(L, "Error",
"Cannot create inotify instance! (%d:%s)", "Cannot create inotify instance! (%d:%s)",
errno, strerror(errno)); errno, strerror(errno));
return -1; // ERRNO exit(-1); // ERRNO
} }
close_exec_fd(inotify_fd); close_exec_fd(inotify_fd);
non_block_fd(inotify_fd); non_block_fd(inotify_fd);
@ -1605,6 +1646,9 @@ main(int argc, char *argv[])
sigaddset(&set, SIGCHLD); sigaddset(&set, SIGCHLD);
signal(SIGCHLD, sig_child); signal(SIGCHLD, sig_child);
sigprocmask(SIG_BLOCK, &set, NULL); sigprocmask(SIG_BLOCK, &set, NULL);
signal(SIGHUP, sig_handler);
signal(SIGTERM, sig_handler);
} }
{ {
@ -1620,7 +1664,53 @@ main(int argc, char *argv[])
masterloop(L); masterloop(L);
/* cleanup */ /* cleanup */
{
/* frees logging categories */
int ci;
struct logcat *lc;
for(ci = 'A'; ci <= 'Z'; ci++) {
for(lc = logcats[ci]; lc && lc->name; lc++) {
free(lc->name);
lc->name = NULL;
}
if (logcats[ci]) {
free(logcats[ci]);
}
}
}
if (lsyncd_config_file) {
free(lsyncd_config_file);
lsyncd_config_file = NULL;
}
/* resets settings to default. */
if (settings.log_file) {
free(settings.log_file);
settings.log_file = NULL;
}
settings.log_syslog = false,
settings.log_level = 0,
settings.nodaemon = false,
/* closes inotify */
close(inotify_fd); close(inotify_fd);
lua_close(L); lua_close(L);
return 0; return 0;
} }
/**
* Main
*/
int
main(int argc, char *argv[])
{
/* kernel parameters */
clocks_per_sec = sysconf(_SC_CLK_TCK);
while(!term) {
main1(argc, argv);
}
return 0;
}

View File

@ -1906,6 +1906,22 @@ end
function runner.cycle(now) function runner.cycle(now)
-- goes through all syncs and spawns more actions -- goes through all syncs and spawns more actions
-- if possible -- if possible
if lsyncdStatus == "fade" then
local np = 0
for _, s in Syncs.iwalk() do
np = np + s.processes:size()
end
if np > 0 then
log("Normal", "waiting for ",np," more child processes.")
return true
else
return false
end
end
if lsyncdStatus ~= "run" then
error("cycle called in not run?!")
end
for _, s in Syncs.iwalk() do for _, s in Syncs.iwalk() do
s:invokeActions(now) s:invokeActions(now)
end end
@ -1913,6 +1929,8 @@ function runner.cycle(now)
if settings.statusFile then if settings.statusFile then
StatusFile.write(now) StatusFile.write(now)
end end
return true
end end
----- -----
@ -2064,7 +2082,7 @@ function runner.initialize()
lockGlobals() lockGlobals()
-- Copies simple settings to "key=true" settings. -- Copies simple settings to "key=true" settings.
for k, v in ipairs(settings) do for k, v in pairs(settings) do
if settings[v] then if settings[v] then
log("Error", "Double setting '"..v.."'") log("Error", "Double setting '"..v.."'")
os.exit(-1) -- ERRNO os.exit(-1) -- ERRNO
@ -2203,8 +2221,24 @@ end
-- Called by core when an overflow happened. -- Called by core when an overflow happened.
-- --
function runner.overflow() function runner.overflow()
log("Error", "--- OVERFLOW on inotify event queue ---") log("Normal", "--- OVERFLOW on inotify event queue ---")
terminate(-1) -- TODO reset instead. lsyncdStatus = "fade"
end
----
-- Called by core on a hup signal.
--
function runner.hup()
log("Normal", "--- HUP signal, resetting ---")
lsyncdStatus = "fade"
end
----
-- Called by core on a term signal.
--
function runner.term()
log("Normal", "--- TERM signal, fading ---")
lsyncdStatus = "fade"
end end
--============================================================================ --============================================================================
@ -2239,6 +2273,9 @@ function spawn(agent, binary, ...)
if agent == nil or type(agent) ~= "table" then if agent == nil or type(agent) ~= "table" then
error("spawning with an invalid agent", 2) error("spawning with an invalid agent", 2)
end end
if lsyncdStatus == "fade" then
log("Normal", "ignored spawn processs since status fading")
end
local pid = lsyncd.exec(binary, ...) local pid = lsyncd.exec(binary, ...)
if pid and pid > 0 then if pid and pid > 0 then
local sync = InletControl.getSync() local sync = InletControl.getSync()