redmine

Porting to FreeBSD, chapter 5: untested kqueue support

language: c
before_install:
- sudo apt-get install libcap-dev libglib2.0-dev libmhash-dev
- sudo apt-get install libcap-dev libglib2.0-dev libmhash-dev libkqueue.*
- sudo pip install cpp-coveralls --use-mirrors
script:
- ./.travis.sh
after_success:
- coveralls -x c --exclude examples --exclude debian --exclude gentoo --exclude autom4te.cache --exclude man --exclude conf*.dir --exclude cluster.c
- coveralls -x c --exclude examples --exclude debian --exclude gentoo --exclude freebsd --exclude m4 --exclude autom4te.cache --exclude man --exclude conf*.dir --exclude cluster.c
... ...
... ... @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
if CLSYNC
bin_PROGRAMS = clsync
clsync_SOURCES = sync.c cluster.c main.c error.c fileutils.c malloc.c glibex.c indexes.c
clsync_SOURCES = sync.c cluster.c main.c error.c fileutils.c malloc.c glibex.c indexes.c calc.c
clsync_CFLAGS = $(AM_CFLAGS)
if HAVE_KQUEUE
... ...
/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "calc.h"
#ifdef HAVE_MHASH
#include <mhash.h>
#endif
#ifndef HAVE_MHASH
/**
* @brief Calculated Adler32 value for char array
*
* @param[in] date Pointer to data
* @param[in] len Length of the data
*
* @retval uint32_t Adler32 value of data
*
*/
// Copied from http://en.wikipedia.org/wiki/Adler-32
uint32_t adler32_calc(unsigned char *data, uint32_t len) { // where data is the location of the data in physical
// memory and len is the length of the data in bytes
const int MOD_ADLER = 65521;
uint32_t a = 1, b = 0;
int32_t index;
// Process each byte of the data in order
for (index = 0; index < len; ++index)
{
a = (a + data[index]) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
}
return (b << 16) | a;
}
#endif
... ...
/*
clsync - file tree sync utility based on inotify/kqueue
Copyright (C) 2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#ifdef HAVE_MHASH
static inline adler32_calc(unsigned char *data, uint32_t len) {
uint32_t adler32;
MHASH td = mhash_init(MHASH_ADLER32);
mhash(td, data, len);
mhash_deinit(td, &adler32);
return adler32;
}
#else
extern uint32_t adler32_calc(unsigned char *data, uint32_t len);
#endif
... ...
... ... @@ -36,12 +36,9 @@
#include "error.h"
#include "cluster.h"
#include "sync.h"
#include "calc.h"
#include "malloc.h"
#ifdef HAVE_MHASH
#include <mhash.h>
#endif
// Global variables. They will be initialized in cluster_init()
#define NODES_ALLOC (MAX(MAXNODES, NODEID_NOID)+1)
... ... @@ -221,36 +218,6 @@ static inline int clustercmd_window_del(window_t *window_p, clustercmdqueuedpack
}
#ifndef HAVE_MHASH
/**
* @brief Calculated Adler32 value for char array
*
* @param[in] date Pointer to data
* @param[in] len Length of the data
*
* @retval uint32_t Adler32 value of data
*
*/
// Copied from http://en.wikipedia.org/wiki/Adler-32
uint32_t adler32_calc(unsigned char *data, int32_t len) { // where data is the location of the data in physical
// memory and len is the length of the data in bytes
const int MOD_ADLER = 65521;
uint32_t a = 1, b = 0;
int32_t index;
// Process each byte of the data in order
for (index = 0; index < len; ++index)
{
a = (a + data[index]) % MOD_ADLER;
b = (b + a) % MOD_ADLER;
}
return (b << 16) | a;
}
#endif
/**
* @brief Calculates Adler32 for clustercmd
*
... ... @@ -277,13 +244,7 @@ int clustercmd_adler32_calc(clustercmd_t *clustercmd_p, clustercmdadler32_t *clu
char *ptr = (char *)&clustercmd_p->h;
// Calculating
#ifdef HAVE_MHASH
MHASH td = mhash_init(MHASH_ADLER32);
mhash(td, ptr, size);
mhash_deinit(td, &adler32);
#else
adler32 = adler32_calc((unsigned char *)ptr, size);
#endif
// Ending
memcpy(&clustercmd_p->h.adler32, &adler32_save, sizeof(clustercmdadler32_t));
... ...
... ... @@ -130,17 +130,11 @@ typedef enum paramsource_enum paramsource_t;
enum notifyengine_enum {
NE_UNDEFINED = 0,
#ifdef FANOTIFY_SUPPORT
NE_FANOTIFY,
#endif
#ifdef INOTIFY_SUPPORT
NE_INOTIFY,
#endif
#ifdef KQUEUE_SUPPORT
NE_KQUEUE,
#endif
};
typedef enum notifyengine_enum notifyenfine_t;
typedef enum notifyengine_enum notifyengine_t;
#define STATE_STARTING(state_p) (state_p == NULL)
enum state_enum {
... ... @@ -260,7 +254,7 @@ struct pushdoubleentry_arg {
struct doubleentry *entry;
};
struct entry {
struct myentry {
size_t size;
size_t alloc;
void *dat;
... ... @@ -270,7 +264,7 @@ struct pushentry_arg {
int allocated;
int total;
size_t size;
struct entry *entry;
struct myentry *entry;
};
enum initsync {
... ...
... ... @@ -29,14 +29,12 @@
// children count limit
#define MAXCHILDREN (1<<8)
#if __linux__
#if INOTIFY_SUPPORT
# define DEFAULT_NOTIFYENGINE NE_INOTIFY
#elif KQUEUE_SUPPORT
# define DEFAULT_NOTIFYENGINE NE_KQUEUE
#else
# if __FreeBSD__
# define DEFAULT_NOTIFYENGINE NE_KQUEUE
# else
# define DEFAULT_NOTIFYENGINE NE_UNDEFINED
# endif
# error No inotify/kqueue support, cannot compile working clsync
#endif
#define DEFAULT_RULES_PERM RA_ALL
#define DEFAULT_COLLECTDELAY 30
... ... @@ -83,3 +81,7 @@
#define DUMP_DIRMODE 0750
#define DUMP_FILEMODE 0644
// size of event chain size to be processes at a time
#define KQUEUE_EVENTLISTSIZE 256
... ...
... ... @@ -97,15 +97,7 @@ enum flags_enum {
CONFIGBLOCKINHERITS = 18|OPTION_LONGOPTONLY,
#ifdef FANOTIFY_SUPPORT
FANOTIFY = 19|OPTION_LONGOPTONLY,
#endif
#ifdef INOTIFY_SUPPORT
INOTIFY = 20|OPTION_LONGOPTONLY,
#endif
#ifdef KQUEUE_SUPPORT
KQUEUE = 21|OPTION_LONGOPTONLY,
#endif
MONITOR = 19|OPTION_LONGOPTONLY,
};
typedef enum flags_enum flags_t;
... ... @@ -177,8 +169,9 @@ struct api_functs {
typedef struct api_functs api_functs_t;
struct notifyenginefuncts {
int (*wait)(int notify_d, struct ctx *ctx_p, struct indexes *indexes_p);
int (*handle)(int notify_d, struct ctx *ctx_p, struct indexes *indexes_p);
int (*wait)(struct ctx *ctx_p, struct timeval *tv_p);
int (*handle)(struct ctx *ctx_p, struct indexes *indexes_p);
int (*add_watch_dir)(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath);
};
struct ctx {
... ... @@ -235,7 +228,6 @@ struct ctx {
api_functs_t handler_funct;
char *rulfpath;
char *listoutdir;
int notifyengine;
struct notifyenginefuncts notifyenginefunct;
int retries;
size_t bfilethreshold;
... ... @@ -248,6 +240,7 @@ struct ctx {
char isignoredexitcode[(1<<8)];
#endif
void *indexes_p;
void *fsmondata;
};
typedef struct ctx ctx_t;
... ...
... ... @@ -18,6 +18,12 @@
*/
#if 0
int fanotify_add_watch_dir(int fanotify_d, struct ctx *ctx_p, const char *const accpath) {
return fanotify_mark(fanotify_d, FAN_MARK_ADD | FAN_MARK_DONT_FOLLOW,
FANOTIFY_MARKMASK, AT_FDCWD, accpath);
}
int fanotify_loop(int fanotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
struct fanotify_event_metadata buf[BUFSIZ/sizeof(struct fanotify_event_metadata) + 1];
int state = STATE_RUNNING;
... ...
... ... @@ -17,3 +17,5 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int fanotify_add_watch_dir(struct ctx *ctx_p, const char *const accpath);
... ...
... ... @@ -26,6 +26,7 @@
char *fd2fpath_malloc(int fd) {
#if __linux__
stat64_t st64;
if(fd <= 0) {
... ... @@ -34,7 +35,6 @@ char *fd2fpath_malloc(int fd) {
return NULL;
}
char *fpath = xmalloc((1<<8) + 2);
sprintf(fpath, "/proc/self/fd/%i", fd);
... ... @@ -57,6 +57,10 @@ char *fd2fpath_malloc(int fd) {
fpath[fpathlen] = 0;
return fpath;
#else
critical("Function fd2fpath_malloc() is not supported in this OS");
return NULL;
#endif
}
/**
... ...
... ... @@ -24,104 +24,19 @@
#include "indexes.h"
#include "inotify.h"
int inotify_wait(int inotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
static struct timeval tv;
time_t tm = time(NULL);
long delay = ((unsigned long)~0 >> 1);
threadsinfo_t *threadsinfo_p = thread_info();
debug(4, "pthread_mutex_unlock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE])");
pthread_cond_broadcast(&threadsinfo_p->cond[PTHREAD_MUTEX_STATE]);
pthread_mutex_unlock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE]);
int inotify_add_watch_dir(ctx_t *ctx_p, indexes_t *indexes_p, const char *const accpath) {
int inotify_d = (int)(long)ctx_p->fsmondata;
return inotify_add_watch(inotify_d, accpath, INOTIFY_MARKMASK);
}
int inotify_wait(ctx_t *ctx_p, struct timeval *tv_p) {
int inotify_d = (int)(long)ctx_p->fsmondata;
debug(3, "select with timeout %li secs.", tv_p->tv_sec);
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(inotify_d, &rfds);
long queue_id = 0;
while(queue_id < QUEUE_MAX) {
queueinfo_t *queueinfo = &ctx_p->_queues[queue_id++];
if(!queueinfo->stime)
continue;
if(queueinfo->collectdelay == COLLECTDELAY_INSTANT) {
debug(3, "There're events in instant queue (#%i), don't waiting.", queue_id-1);
return 0;
}
int qdelay = queueinfo->stime + queueinfo->collectdelay - tm;
debug(3, "queue #%i: %i %i %i -> %i", queue_id-1, queueinfo->stime, queueinfo->collectdelay, tm, qdelay);
if(qdelay < -(long)ctx_p->syncdelay)
qdelay = -(long)ctx_p->syncdelay;
delay = MIN(delay, qdelay);
}
long synctime_delay = ((long)ctx_p->synctime) - ((long)tm);
synctime_delay = synctime_delay > 0 ? synctime_delay : 0;
debug(3, "delay = MAX(%li, %li)", delay, synctime_delay);
delay = MAX(delay, synctime_delay);
delay = delay > 0 ? delay : 0;
if(ctx_p->flags[THREADING]) {
time_t _thread_nextexpiretime = thread_nextexpiretime();
debug(3, "thread_nextexpiretime == %i", _thread_nextexpiretime);
if(_thread_nextexpiretime) {
long thread_expiredelay = (long)thread_nextexpiretime() - (long)tm + 1; // +1 is to make "tm>threadinfo_p->expiretime" after select() definitely TRUE
debug(3, "thread_expiredelay == %i", thread_expiredelay);
thread_expiredelay = thread_expiredelay > 0 ? thread_expiredelay : 0;
debug(3, "delay = MIN(%li, %li)", delay, thread_expiredelay);
delay = MIN(delay, thread_expiredelay);
}
}
if((!delay) || (*state_p != STATE_RUNNING))
return 0;
if(ctx_p->flags[EXITONNOEVENTS]) { // zero delay if "--exit-on-no-events" is set
tv.tv_sec = 0;
tv.tv_usec = 0;
} else {
debug(3, "sleeping for %li second(s).", SLEEP_SECONDS);
sleep(SLEEP_SECONDS);
delay = ((long)delay)>SLEEP_SECONDS ? delay-SLEEP_SECONDS : 0;
tv.tv_sec = delay;
tv.tv_usec = 0;
}
debug(4, "pthread_mutex_lock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE])");
pthread_mutex_lock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE]);
if(*state_p != STATE_RUNNING)
return 0;
debug(4, "pthread_mutex_unlock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE])");
pthread_cond_broadcast(&threadsinfo_p->cond[PTHREAD_MUTEX_STATE]);
pthread_mutex_lock(&threadsinfo_p->mutex[PTHREAD_MUTEX_SELECT]);
pthread_mutex_unlock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE]);
debug(3, "select with timeout %li secs.", tv.tv_sec);
int ret = select(inotify_d+1, &rfds, NULL, NULL, &tv);
pthread_mutex_unlock(&threadsinfo_p->mutex[PTHREAD_MUTEX_SELECT]);
if((ret == -1) && (errno == EINTR)) {
errno = 0;
ret = 0;
}
debug(4, "pthread_mutex_lock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE])");
pthread_mutex_lock(&threadsinfo_p->mutex[PTHREAD_MUTEX_STATE]);
if((ctx_p->flags[EXITONNOEVENTS]) && (ret == 0)) // if not events and "--exit-on-no-events" is set
*state_p = STATE_EXIT;
return ret;
return select(inotify_d+1, &rfds, NULL, NULL, tv_p);
}
#define INOTIFY_HANDLE_CONTINUE {\
... ... @@ -130,8 +45,9 @@ int inotify_wait(int inotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
continue;\
}
int inotify_handle(int inotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
int inotify_handle(ctx_t *ctx_p, indexes_t *indexes_p) {
static struct timeval tv={0};
int inotify_d = (int)(long)ctx_p->fsmondata;
int count = 0;
... ... @@ -199,7 +115,7 @@ int inotify_handle(int inotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
mode_t st_mode;
size_t st_size;
if (lstat64(path_full, &lstat)) {
debug(2, "Cannot lstat(\"%s\", lstat). Seems, that the object disappeared.", path_full);
debug(2, "Cannot lstat64(\"%s\", lstat). Seems, that the object disappeared.", path_full);
if(event->mask & IN_ISDIR)
st_mode = S_IFDIR;
else
... ... @@ -210,7 +126,7 @@ int inotify_handle(int inotify_d, ctx_t *ctx_p, indexes_t *indexes_p) {
st_size = lstat.st_size;
}
if (sync_prequeue_loadmark(inotify_d, ctx_p, indexes_p, path_full, NULL, event->mask, event->wd, st_mode, st_size, &path_rel, &path_rel_len, NULL)) {
if (sync_prequeue_loadmark(1, ctx_p, indexes_p, path_full, NULL, event->mask, event->wd, st_mode, st_size, &path_rel, &path_rel_len, NULL)) {
count = -1;
goto l_inotify_handle_end;
}
... ... @@ -232,3 +148,10 @@ l_inotify_handle_end:
return count;
}
int inotify_deinit(ctx_t *ctx_p) {
int inotify_d = (int)(long)ctx_p->fsmondata;
debug(3, "Closing inotify_d");
return close(inotify_d);
}
... ...
... ... @@ -17,6 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
extern int inotify_wait(int inotify_d, struct ctx *ctx_p, struct indexes *indexes_p);
extern int inotify_handle(int inotify_d, struct ctx *ctx_p, struct indexes *indexes_p);
extern int inotify_wait(struct ctx *ctx_p, struct timeval *tv_p);
extern int inotify_handle(struct ctx *ctx_p, struct indexes *indexes_p);
extern int inotify_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath);
extern int inotify_deinit(ctx_t *ctx_p);
... ...
This diff is collapsed. Click to expand it.
... ... @@ -39,7 +39,9 @@
#define IN_ISDIR 0x40000000
#endif
extern int kqueue_add_watch(int kqueue_d, const char *const accpath);
extern int kqueue_wait(int kqueue_d, struct ctx *ctx_p, struct indexes *indexes_p);
extern int kqueue_handle(int kqueue_d, struct ctx *ctx_p, struct indexes *indexes_p);
extern int kqueue_init();
extern int kqueue_add_watch_dir(struct ctx *ctx_p, struct indexes *indexes_p, const char *const accpath);
extern int kqueue_wait(struct ctx *ctx_p, struct timeval *tv_p);
extern int kqueue_handle(struct ctx *ctx_p, struct indexes *indexes_p);
extern int kqueue_deinit(ctx_t *ctx_p);
... ...
... ... @@ -97,15 +97,7 @@ static const struct option long_options[] =
{"debug", optional_argument, NULL, DEBUG},
{"dump-dir", required_argument, NULL, DUMPDIR},
{"quiet", optional_argument, NULL, QUIET},
#ifdef FANOTIFY_SUPPORT
{"fanotify", optional_argument, NULL, FANOTIFY},
#endif
#ifdef INOTIFY_SUPPORT
{"inotify", optional_argument, NULL, INOTIFY},
#endif
#ifdef KQUEUE_SUPPORT
{"kqueue", optional_argument, NULL, KQUEUE},
#endif
{"monitor", required_argument, NULL, MONITOR},
{"label", required_argument, NULL, LABEL},
{"help", optional_argument, NULL, HELP},
{"version", optional_argument, NULL, SHOW_VERSION},
... ... @@ -127,6 +119,12 @@ static char *const threading_modes[] = {
NULL
};
static char *const notify_engines[] = {
[NE_INOTIFY] = "inotify",
[NE_KQUEUE] = "kqueue",
[NE_FANOTIFY] = "fanotify",
};
static char *const output_methods[] = {
[OM_STDERR] = "stderr",
[OM_STDOUT] = "stdout",
... ... @@ -446,21 +444,44 @@ int parse_parameter(ctx_t *ctx_p, uint16_t param_id, char *arg, paramsource_t pa
case BFILETHRESHOLD:
ctx_p->bfilethreshold = (unsigned long)atol(arg);
break;
#ifdef FANOTIFY_SUPPORT
case FANOTIFY:
ctx_p->notifyengine = NE_FANOTIFY;
break;
case MONITOR: {
char *value, *arg_orig = arg;
if (!*arg) {
ctx_p->flags_set[param_id] = 0;
return 0;
}
notifyengine_t notifyengine = getsubopt(&arg, notify_engines, &value);
if((int)notifyengine == -1) {
errno = EINVAL;
error("Invalid FS monitor subsystem entered: \"%s\"", arg_orig);
return EINVAL;
}
switch (notifyengine) {
#ifndef FANOTIFY_SUPPORT
case NE_FANOTIFY:
#endif
#ifdef INOTIFY_SUPPORT
case INOTIFY:
ctx_p->notifyengine = NE_INOTIFY;
break;
#ifndef INOTIFY_SUPPORT
case NE_INOTIFY:
#endif
#ifdef KQUEUE_SUPPORT
case KQUEUE:
ctx_p->notifyengine = NE_KQUEUE;
break;
case NE_KQUEUE:
#endif
error(PROGRAM" is compiled without %s subsystem support. Recompile with option \"--with-%s\" if you're planning to use it.", arg_orig, arg_orig);
return EINVAL;
default:
#ifdef VERYPARANOID
critical("Internal error");
#endif
break;
}
ctx_p->flags[MONITOR] = notifyengine;
break;
}
case RSYNCINCLIMIT:
ctx_p->rsyncinclimit = (unsigned int)atol(arg);
break;
... ... @@ -1125,7 +1146,7 @@ int main(int argc, char *argv[]) {
memset(&ctx, 0, sizeof(ctx));
int ret = 0, nret;
ctx.notifyengine = DEFAULT_NOTIFYENGINE;
ctx.flags[MONITOR] = DEFAULT_NOTIFYENGINE;
ctx.syncdelay = DEFAULT_SYNCDELAY;
ctx._queues[QUEUE_NORMAL].collectdelay = DEFAULT_COLLECTDELAY;
ctx._queues[QUEUE_BIGFILE].collectdelay = DEFAULT_BFILECOLLECTDELAY;
... ... @@ -1147,9 +1168,9 @@ int main(int argc, char *argv[]) {
error_init(&ctx.flags[OUTPUT_METHOD], &ctx.flags[QUIET], &ctx.flags[VERBOSE], &ctx.flags[DEBUG]);
nret = arguments_parse(argc, argv, &ctx);
if(nret) ret = nret;
if (nret) ret = nret;
if(!ret) {
if (!ret) {
nret = configs_parse(&ctx);
if(nret) ret = nret;
}
... ... @@ -1538,11 +1559,11 @@ int main(int argc, char *argv[]) {
}
#ifdef FANOTIFY_SUPPORT
if(ctx.notifyengine == NE_FANOTIFY)
if (ctx.flags[MONITOR] == NE_FANOTIFY)
critical("fanotify is not supported, now!");
else
#endif
if(ctx.notifyengine == NE_UNDEFINED) {
if (ctx.flags[MONITOR] == NE_UNDEFINED) {
ret = errno = EINVAL;
error("Required one of next options:"
#ifdef INOTIFY_SUPPORT
... ... @@ -1554,7 +1575,7 @@ int main(int argc, char *argv[]) {
);
}
if(ctx.flags[EXITHOOK]) {
if (ctx.flags[EXITHOOK]) {
#ifdef VERYPARANOID
if(ctx.exithookfile == NULL) {
ret = errno = EINVAL;
... ...
... ... @@ -842,30 +842,56 @@ Is not set by default.
.RE
.PP
.B \-\-fanotify
.B \-\-monitor
.I monitor\-subsystem
.RS 8
.B Don't use this option!
Switches FS monitor subsystem.
Switches monitor subsystem to "fanotify" [it's described for
future\-compatibility].
Possible values:
.RS 8
.IR inotify
.RS
.BR inotify (7)
Is not set by default.
.RE
Native, fast, reliable and well tested Linux FS monitor subsystem.
.PP
.B \-\-inotify
.RS 8
Switches monitor subsystem to "inotify".
There's no performance profit to use "inotify" instead of "kevent" on FreeBSD
using "libinotify". It backends to "kevent" anyway. However inotify support is
well tested and may be useful even via "libinotify".
Is set by default on Linux.
.RE
.IR kqueue
.RS
.BR kqueue (2)
.PP
.B \-\-kqueue
.RS 8
Switches monitor subsystem to "kqueue/kevent".
A *BSD kernel event notification mechanism (inc. timer, sockets, files etc).
Is set by default on FreeBSD.
This monitor subsystem that cannot determine file creation event, but it can
determine a directory where something happened. So
.B clsync
is have to rescan whole dir every time on any content change.
Also this API requires to open every monitored file and directory. So it may
produce a huge amount of file descriptors. Be sure that
.I kern.maxfiles
is big enough (in FreeBSD).
CPU/HDD expensive way.
.B Not well tested. Use with caution!
.br
.B Warning! May be problems with hard links.
FreeBSD users: notify me about found bugs, please. And before the bugfix
you can switch to "inotify" through libinotify.
.RE
.RE
If
.B inotify
is supported (even through libinotify) then it's used by default. If not then
.B kqueue
is used.
.RE
.PP
... ... @@ -1517,4 +1543,5 @@ Don't be afraid to ask about clsync configuration, ;).
.BR rsync (1),
.BR pthreads (7),
.BR inotify (7)
.BR kqueue (2)
... ...
This diff is collapsed. Click to expand it.