working on fsevents

This commit is contained in:
Axel Kittenberger 2010-12-07 15:42:46 +00:00
parent 2f21d0f0b8
commit 44e0e45594
4 changed files with 200 additions and 133 deletions

View File

@ -2,16 +2,16 @@ AUTOMAKE_OPTIONS = foreign
CFLAGS += -Wall $(LUA_CFLAGS) CFLAGS += -Wall $(LUA_CFLAGS)
bin_PROGRAMS = lsyncd bin_PROGRAMS = lsyncd
lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua lsyncd_SOURCES = lsyncd.h lsyncd.c lsyncd.lua
#if INOTIFY if INOTIFY
lsyncd_SOURCES += inotify.c lsyncd_SOURCES += inotify.c
#endif endif
#if FANOTIFY if FANOTIFY
#lsyncd_SOURCES += fanotify.c lsyncd_SOURCES += fanotify.c
#endif endif
#if FSEVENTS if FSEVENTS
#lsyncd_SOURCES += fsevents.c lsyncd_SOURCES += fsevents.c
#endif endif
lsyncd_LDADD = $(LUA_LIBS) lsyncd_LDADD = $(LUA_LIBS)
exampledir = $(datarootdir)/doc/@PACKAGE@ exampledir = $(datarootdir)/doc/@PACKAGE@

View File

@ -41,44 +41,44 @@ AM_CONDITIONAL([RUNNER], [test x${with_runner} != x])
## With this release Lsyncd can yet only do with inotify. ## With this release Lsyncd can yet only do with inotify.
## enabling fsevents and disabling inotify is thus commented out. ## enabling fsevents and disabling inotify is thus commented out.
#### ###
## --without-inotify option # --without-inotify option
#AC_ARG_WITH([inotify], AC_ARG_WITH([inotify],
#[ --without-inotify Do not use Linux inotify event interface. On by default.]) [ --without-inotify Do not use Linux inotify event interface. On by default.])
#if test "x${with_inotify}" == xno; then if test "x${with_inotify}" == xno; then
# echo "compiling without inotify" echo "compiling without inotify"
#else else
echo "compiling with inotify" echo "compiling with inotify"
AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr") AC_DEFINE(LSYNCD_WITH_INOTIFY,,"descr")
#fi fi
AM_CONDITIONAL([INOTIFY], [test x${with_inotify} != xno]) AM_CONDITIONAL([INOTIFY], [test x${with_inotify} != xno])
#### ###
## --with-fanotify option # --with-fanotify option
## #
#AC_ARG_WITH([fanotify], AC_ARG_WITH([fanotify],
#[ --with-fanotify Uses Linux new fanotify event interface. EXPERIMENTAL! [ --with-fanotify Uses Linux new fanotify event interface. EXPERIMENTAL!
# Off by default.]) Off by default.])
##if test "x${with_fanotify}" == xno; then if test "x${with_fanotify}" == x || test "x${with_fanotify}no" == xno; then
# echo "compiling without fanotify" echo "compiling without fanotify"
#else else
# echo "compiling with fanotify - WARNING experimental!" echo "compiling with fanotify - WARNING experimental!"
# AC_DEFINE(LSYNCD_WITH_FANOTIFY,,"descr") AC_DEFINE(LSYNCD_WITH_FANOTIFY,,"descr")
##fi fi
AM_CONDITIONAL([FANOTIFY], AM_CONDITIONAL([FANOTIFY],
[test x${with_fanotify} != x -a x${with_fanotify} != xno]) [test x${with_fanotify} != x -a x${with_fanotify} != xno])
#### ###
## --with-fsevents # --with-fsevents
#AC_ARG_WITH([fsevents], AC_ARG_WITH([fsevents],
#[ --with-fsevents Uses MacOS (10.5) /dev/fsevents. EXPERIMENTAL! [ --with-fsevents Uses MacOS (10.5) /dev/fsevents. EXPERIMENTAL!
# Off by default.]) Off by default.])
#if test "x${with_fsevents}" != x; then if test "x${with_fsevents}" != x; then
# echo "compiling with fsevents. WARNING experimental!" echo "compiling with fsevents. WARNING experimental!"
# AC_DEFINE(LSYNCD_WITH_FSEVENTS,,"descr") AC_DEFINE(LSYNCD_WITH_FSEVENTS,,"descr")
#else else
# echo "compiling without fsevents" echo "compiling without fsevents"
#fi fi
AM_CONDITIONAL([FSEVENTS], AM_CONDITIONAL([FSEVENTS],
[test x${with_fsevents} != x -a xno${with_fsevents} != xno]) [test x${with_fsevents} != x -a xno${with_fsevents} != xno])

View File

@ -25,9 +25,6 @@
* including Spotlight. Consequently, Spotlight may need to look at the entire * including Spotlight. Consequently, Spotlight may need to look at the entire
* volume to determine "what changed". * volume to determine "what changed".
*/ */
#error "This code is not yet finished."
#include "lsyncd.h" #include "lsyncd.h"
#include <sys/types.h> #include <sys/types.h>
@ -90,7 +87,8 @@ struct kfs_event {
pid_t pid; pid_t pid;
/* event arguments */ /* event arguments */
struct kfs_event_arg args[KFS_NUM_ARGS]; struct kfs_event_arg args[];
/* struct kfs_event_arg args[KFS_NUM_ARGS]; */
}; };
/** /**
@ -102,7 +100,7 @@ static const luaL_reg lfseventslib[] = {
{NULL, NULL} {NULL, NULL}
}; };
// event names /* event names */
static const char *eventNames[FSE_MAX_EVENTS] = { static const char *eventNames[FSE_MAX_EVENTS] = {
"CREATE_FILE", "CREATE_FILE",
"DELETE", "DELETE",
@ -117,9 +115,111 @@ static const char *eventNames[FSE_MAX_EVENTS] = {
"XATTR_REMOVED", "XATTR_REMOVED",
}; };
/* argument names*/
static const char *argNames[] = {
"UNKNOWN",
"VNODE",
"STRING",
"PATH",
"INT32",
"INT64",
"RAW",
"INO",
"UID",
"DEV",
"MODE",
"GID",
"FINFO",
};
/**
* The read buffer
*/
static size_t const readbuf_size = 131072; static size_t const readbuf_size = 131072;
static char * readbuf = NULL; static char * readbuf = NULL;
/**
* Handles one fsevents event
* @returns the size of the event
*/
static ssize_t
handle_event(lua_State *L, struct kfs_event *event, ssize_t mlen)
{
/* the len of the event */
ssize_t len = sizeof(int32_t) + sizeof(pid_t);
bool want_path = false;
const char *path = NULL;
if (event->type == FSE_EVENTS_DROPPED) {
logstring("Fsevents", "Events dropped!");
load_runner_func(L, "overflow");
if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO
}
lua_pop(L, 1);
hup = 1;
len += sizeof(u_int16_t);
return len;
}
{
int32_t atype = event->type & FSE_TYPE_MASK;
uint32_t aflags = FSE_GET_FLAGS(event->type);
if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) {
printlogf(L, "Fsevents", "got event %s", eventNames[atype]);
if (aflags & FSE_COMBINED_EVENTS) {
logstring("Fsevents", "combined events");
}
if (aflags & FSE_CONTAINS_DROPPED_EVENTS) {
logstring("Fsevents", "contains dropped events");
}
} else {
printlogf(L, "Error", "unknown event(%d) in fsevents.",
atype);
exit(-1); // ERRNO
}
switch(atype) {
case FSE_CREATE_FILE :
want_path = true;
break;
}
}
{
struct kfs_event_arg *arg = event->args;
while (len < mlen) {
int eoff;
if (arg->type == FSE_ARG_DONE) {
logstring("Fsevents", "argdone");
len += sizeof(u_int16_t);
break;
}
switch (arg->type) {
case FSE_ARG_STRING :
if (want_path && !path) {
path = arg->data.str;
}
break;
}
eoff = sizeof(arg->type) + sizeof(arg->len) + arg->len;
len += eoff;
printlogf(L, "Fsevents", "arg:%s:%d",
argNames[arg->type > FSE_MAX_ARGS ? 0 : arg->type],
arg->len);
arg = (struct kfs_event_arg *) ((char *) arg + eoff);
}
}
if (path) {
// printlogf(L, "path=%s", path);
}
return len;
}
/** /**
* Called when fsevents has something to read * Called when fsevents has something to read
*/ */
@ -141,7 +241,7 @@ fsevents_ready(lua_State *L, struct observance *obs)
} }
if (len < 0) { if (len < 0) {
if (err == EAGAIN) { if (err == EAGAIN) {
/* nothing more inotify */ /* nothing more */
break; break;
} else { } else {
printlogf(L, "Error", "Read fail on fsevents"); printlogf(L, "Error", "Read fail on fsevents");
@ -150,40 +250,9 @@ fsevents_ready(lua_State *L, struct observance *obs)
} }
{ {
int off = 0; int off = 0;
int32_t atype;
uint32_t aflags;
while (off < len && !hup && !term) { while (off < len && !hup && !term) {
struct kfs_event *event = (struct kfs_event *) &readbuf[off]; struct kfs_event *event = (struct kfs_event *) &readbuf[off];
off += sizeof(int32_t) + sizeof(pid_t); off += handle_event(L, event, len);
if (event->type == FSE_EVENTS_DROPPED) {
logstring("Fsevents", "Events dropped!");
load_runner_func(L, "overflow");
if (lua_pcall(L, 0, 0, -2)) {
exit(-1); // ERRNO
}
lua_pop(L, 1);
hup = 1;
off += sizeof(u_int16_t);
continue;
}
atype = event->type & FSE_TYPE_MASK;
aflags = FSE_GET_FLAGS(event->type);
if ((atype < FSE_MAX_EVENTS) && (atype >= -1)) {
printlogf(L, "Fsevents", "got event %s", eventNames[atype]);
if (aflags & FSE_COMBINED_EVENTS) {
logstring("Fsevents", "combined events");
}
if (aflags & FSE_CONTAINS_DROPPED_EVENTS) {
logstring("Fsevents", "contains dropped events");
}
} else {
printlogf(L, "Error", "unknown event(%d) in fsevents.",
atype);
exit(-1); // ERRNO
}
} }
} }
} }
@ -220,8 +289,6 @@ register_fsevents(lua_State *L) {
extern void extern void
open_fsevents(lua_State *L) open_fsevents(lua_State *L)
{ {
return;
int8_t event_list[] = { // action to take for each event int8_t event_list[] = { // action to take for each event
FSE_REPORT, /* FSE_CREATE_FILE */ FSE_REPORT, /* FSE_CREATE_FILE */
FSE_REPORT, /* FSE_DELETE */ FSE_REPORT, /* FSE_DELETE */

View File

@ -1871,60 +1871,60 @@ local Inotify = (function()
} }
end)() end)()
------
---- Interface to OSX /dev/fsevents, watches the whole filesystems
---- ----
---- All fsevents specific implementation should be enclosed here. -- Interface to OSX /dev/fsevents, watches the whole filesystems
----
--local Fsevents = (function()
-- -----
-- -- A list indexed by sync's containing the root path this
-- -- sync is interested in.
-- --
-- local syncPaths = {}
-- --
-- ----- -- All fsevents specific implementation should be enclosed here.
-- -- adds a Sync to receive events
-- --
-- -- @param sync Object to receive events
-- -- @param dir dir to watch
-- --
-- local function addSync(sync, dir)
-- if syncRoots[sync] then
-- error("duplicate sync in Fanotify.addSync()")
-- end
-- -- TODO for non subdirs adddir only
-- syncRoots[sync] = dir
-- end
-- --
-- ----- local Fsevents = (function()
-- -- Called when any event has occured. -----
-- -- -- A list indexed by sync's containing the root path this
-- -- @param etype "Attrib", "Mofify", "Create", "Delete", "Move") -- sync is interested in.
-- -- @param wd watch descriptor (matches lsyncd.inotifyadd())
-- -- @param isdir true if filename is a directory
-- -- @param time time of event
-- -- @param filename string filename without path
-- -- @param filename2
-- --
-- local function event(etype, isdir, time, filename, filename2)
-- log("Fsevents", etype, isdir, time, filename, filename2)
-- end
-- --
-- ----- local syncRoots = {}
-- -- Writes a status report about inotifies to a filedescriptor
-- -- -----
-- local function statusReport(f) -- adds a Sync to receive events
-- -- TODO
-- end
-- --
-- -- public interface -- @param sync Object to receive events
-- return { -- @param dir dir to watch
-- addSync = addSync, --
-- event = event, local function addSync(sync, dir)
-- statusReport = statusReport if syncRoots[sync] then
-- } error("duplicate sync in Fanotify.addSync()")
--end)() end
-- TODO for non subdirs adddir only
syncRoots[sync] = dir
end
-----
-- Called when any event has occured.
--
-- @param etype "Attrib", "Mofify", "Create", "Delete", "Move")
-- @param wd watch descriptor (matches lsyncd.inotifyadd())
-- @param isdir true if filename is a directory
-- @param time time of event
-- @param filename string filename without path
-- @param filename2
--
local function event(etype, isdir, time, filename, filename2)
log("Fsevents", etype, isdir, time, filename, filename2)
end
-----
-- Writes a status report about inotifies to a filedescriptor
--
local function statusReport(f)
-- TODO
end
-- public interface
return {
addSync = addSync,
event = event,
statusReport = statusReport
}
end)()
----- -----
-- Holds information about the event monitor capabilities -- Holds information about the event monitor capabilities
@ -2643,7 +2643,7 @@ function runner.initialize()
for _, s in Syncs.iwalk() do for _, s in Syncs.iwalk() do
if s.config.monitor == "inotify" then if s.config.monitor == "inotify" then
Inotify.addSync(s, s.source) Inotify.addSync(s, s.source)
elseif s.config.monitor == "fanotify" then elseif s.config.monitor == "fsevents" then
Fsevents.addSync(s, s.source) Fsevents.addSync(s, s.source)
else else
error("sync "..s.config.name.. error("sync "..s.config.name..