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.
--
-- This example uses local bash commands to keep two local
-- directory trees in sync.
--
settings = {
statusFile = "/tmp/lsyncd.stat",
logfile = "/tmp/lsyncd.log",
statusFile = "/tmp/lsyncd.stat",
statusIntervall = 1,
nodaemon = true,
}
----
-----
-- for testing purposes. prefix can be used to slow commands down.
-- prefix = "sleep 5 && "
--
prefix = ""
----
-----
-- for testing purposes. uses bash command to hold local dirs in sync.
--
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.
*/
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.
@ -141,6 +142,24 @@ sig_child(int sig)
{
/* nothing */
}
/**
* signal handler
*/
void
sig_handler(int sig)
{
switch (sig) {
case SIGTERM:
term = 1;
return;
case SIGHUP:
hup = 1;
return;
}
}
/**
* predeclerations -- see below
*/
@ -297,7 +316,7 @@ logstring0(int priority, const char *cat, const char *message)
settings.log_file);
exit(-1); // ERRNO
}
fprintf(flog, "%s %s: %s", ct, cat, message);
fprintf(flog, "%s %s: %s\n", ct, cat, message);
fclose(flog);
}
@ -873,7 +892,7 @@ l_subdirs (lua_State *L)
}
lua_newtable(L);
while (!reset) {
while (!hup && !term) {
struct dirent *de = readdir(d);
bool isdir;
if (de == NULL) {
@ -957,7 +976,7 @@ l_configure(lua_State *L)
* from this on log to configurated log end instead of
* stdout/stderr */
running = true;
if (!settings.nodaemon) {
if (!settings.nodaemon && !is_daemon) {
if (!settings.log_file) {
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 */
struct inotify_event *after_buf = NULL;
if (reset) {
if (hup || term) {
return;
}
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");
if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO
}
lua_pop(L, 1);
hup = 1;
return;
}
/* cancel on ignored or resetting */
@ -1188,7 +1208,7 @@ masterloop(lua_State *L)
{
size_t readbuf_size = 2048;
char *readbuf = s_malloc(readbuf_size);
while(!reset) {
while(true) {
bool have_alarm;
clock_t now = times(NULL);
clock_t alarm_time;
@ -1283,7 +1303,7 @@ masterloop(lua_State *L)
/* nothing more inotify */
break;
}
while (i < len && !reset) {
while (i < len && !hup && !term) {
struct inotify_event *event =
(struct inotify_event *) &readbuf[i];
handle_event(L, event);
@ -1343,14 +1363,38 @@ masterloop(lua_State *L)
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,
* like starting new processes, writing the statusfile etc. */
load_runner_func(L, "cycle");
lua_pushinteger(L, times(NULL));
if (lua_pcall(L, 1, 0, -3)) {
if (lua_pcall(L, 1, 1, -3)) {
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
*/
int
main(int argc, char *argv[])
main1(int argc, char *argv[])
{
/* the Lua interpreter */
lua_State* L;
@ -1369,9 +1413,6 @@ main(int argc, char *argv[])
int argp = 1;
/* kernel parameters */
clocks_per_sec = sysconf(_SC_CLK_TCK);
/* load Lua */
L = lua_open();
luaL_openlibs(L);
@ -1383,11 +1424,11 @@ main(int argc, char *argv[])
version = luaL_checkstring(L, -1);
if (sscanf(version, "Lua %d.%d", &major, &minor) != 2) {
fprintf(stderr, "cannot parse lua library version!\n");
return -1; // ERRNO
exit(-1); // ERRNO
}
if ((major < 5) || (major == 5 && minor < 1)) {
fprintf(stderr, "lua library is too old. Need 5.1 at least");
return -1; // ERRNO
exit(-1); // ERRNO
}
lua_pop(L, 1);
}
@ -1407,7 +1448,7 @@ main(int argc, char *argv[])
if (!add_logcat(argv[i], LOG_NOTICE)) {
printlogf(L, "Error", "'%s' is not a valid logging category",
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",
"%s --runner RUNNER_FILE CONFIG_FILE", argv[0]);
return -1; // ERRNO
exit(-1); // ERRNO
}
/* loads the runner file */
if (luaL_loadfile(L, lsyncd_runner_file)) {
printlogf(L, "Error",
"error loading '%s': %s",
lsyncd_runner_file, lua_tostring(L, -1));
return -1; // ERRNO
exit(-1); // ERRNO
}
} else {
#ifndef LSYNCD_DEFAULT_RUNNER_FILE
@ -1470,13 +1511,13 @@ main(int argc, char *argv[])
printlogf(L, "Error",
"error loading precompiled lsyncd.lua runner: %s",
lua_tostring(L, -1));
return -1; // ERRNO
exit(-1); // ERRNO
}
#else
/* this should never be possible, security code nevertheless */
logstring("Error",
"Internal fail: lsyncd_runner is NULL with non-static runner");
return -1; // ERRNO
exit(-1); // ERRNO
#endif
}
@ -1488,7 +1529,7 @@ main(int argc, char *argv[])
"error preparing '%s': %s",
lsyncd_runner_file ? lsyncd_runner_file : "internal runner",
lua_tostring(L, -1));
return -1; // ERRNO
exit(-1); // ERRNO
}
lua_pushlightuserdata(L, (void *)&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'",
lsyncd_runner_file ? lsyncd_runner_file : "internal runner",
lversion, PACKAGE_VERSION);
return -1; // ERRNO
exit(-1); // ERRNO
}
lua_pop(L, 1);
}
@ -1533,7 +1574,7 @@ main(int argc, char *argv[])
exit(-1); // ERRNO
}
lua_pop(L, 1);
return -1; // ERRNO
exit(-1); // ERRNO
}
}
}
@ -1567,7 +1608,7 @@ main(int argc, char *argv[])
printlogf(L, "Error",
"Cannot find config file at '%s'.",
lsyncd_config_file);
return -1; // ERRNO
exit(-1); // ERRNO
}
/* loads and executes the config file */
@ -1575,13 +1616,13 @@ main(int argc, char *argv[])
printlogf(L, "Error",
"error loading %s: %s",
lsyncd_config_file, lua_tostring(L, -1));
return -1; // ERRNO
exit(-1); // ERRNO
}
if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
printlogf(L, "Error",
"error preparing %s: %s",
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",
"Cannot create inotify instance! (%d:%s)",
errno, strerror(errno));
return -1; // ERRNO
exit(-1); // ERRNO
}
close_exec_fd(inotify_fd);
non_block_fd(inotify_fd);
@ -1605,6 +1646,9 @@ main(int argc, char *argv[])
sigaddset(&set, SIGCHLD);
signal(SIGCHLD, sig_child);
sigprocmask(SIG_BLOCK, &set, NULL);
signal(SIGHUP, sig_handler);
signal(SIGTERM, sig_handler);
}
{
@ -1620,7 +1664,53 @@ main(int argc, char *argv[])
masterloop(L);
/* 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);
lua_close(L);
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)
-- goes through all syncs and spawns more actions
-- 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
s:invokeActions(now)
end
@ -1913,6 +1929,8 @@ function runner.cycle(now)
if settings.statusFile then
StatusFile.write(now)
end
return true
end
-----
@ -2064,7 +2082,7 @@ function runner.initialize()
lockGlobals()
-- 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
log("Error", "Double setting '"..v.."'")
os.exit(-1) -- ERRNO
@ -2203,8 +2221,24 @@ end
-- Called by core when an overflow happened.
--
function runner.overflow()
log("Error", "--- OVERFLOW on inotify event queue ---")
terminate(-1) -- TODO reset instead.
log("Normal", "--- OVERFLOW on inotify event queue ---")
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
--============================================================================
@ -2239,6 +2273,9 @@ function spawn(agent, binary, ...)
if agent == nil or type(agent) ~= "table" then
error("spawning with an invalid agent", 2)
end
if lsyncdStatus == "fade" then
log("Normal", "ignored spawn processs since status fading")
end
local pid = lsyncd.exec(binary, ...)
if pid and pid > 0 then
local sync = InletControl.getSync()