redmine

README file was been updated

Notify engines:
Contents:
It's suppported fanotify and inotify engines. However fanotify was not ready
at the moment of the code writting, so I was have to temporary fallback
to inotify.
0.) Name
1.) Motivation
2.) inotify vs fanotify
3.) How to use
4.) Known issues
5.) Support
I've freezed code that uses fanotify until it the fanotify will be ready.
_____________________________________________
The reason, why I didn't continue to use fanotify, that it was unable to
catch some events, like "directory creation" or "file deletion".
0.) Name
Why "clsync"? The first name of the utility was "insync" (due to inotify), but
then I suggested to use "fanotify" instead of "inotify" and utility was been
renamed to "fasync". After that I started to intensively write the program.
However I faced with some problems in "fanotify", so I was have to temporary
fallback to "inotify", then I decided, that the best name is "Runtime Sync" or
"Live Sync", but "rtsync" is a name of some corporation, and "lsync" is busy
by "lsyncd" project ("https://github.com/axkibe/lsyncd"). So I called it
"clsync", that should be interpreted as "lsync, but on c" due to "lsyncd" that
written on "LUA" and may be used for the same purposes.
_____________________________________________
1.) Motivation
This utility was been writted for two purposes:
- for making failover clusters
- for making backups of them
To do failover cluster I've tried a lot of different solutions, like "simple
rsync by cron", "glusterfs", "ocfs2 over drbd", "common mirrorable external
storage", "incron + perl + rsync", "inosync", "lsyncd" and so on. Currently we
are using "lsyncd", "ceph" and "ocfs2 over drbd". However all of this
solutions doesn't arrange me, so I was have to write own utility for this
purpose.
To do backups we also tried a lot of different solution, and again I was have
to write own utility for this purpose.
The best known (for me) replacement for this utility is "lsyncd", however:
- It's code is >½ on LUA. There a lot of problems connected with it,
for example:
- It's more difficult to maintain the code with ordinary sysadmin.
- It really eats 100% CPU sometimes, however author of "lsyncd"
ensures, that "LUA" is fast enough.
- It required LUA libs, that cannot be easily installed to few
of our systems.
- It a little buggy. That may be easily fixed for our cases, but LUA:(
- It doesn't support pthread or something like that to serve huge
directories with a lot of containers right.
- It cannot run rsync for a pack of files. It runs rsync for every
event. :(
- It can't set another event-collecting delay for big files. We don't
want to sync big files (>1GiB) so often as ordinary files.
_____________________________________________
2.) inotify vs fanotify:
It's said, that fanotify is much better, than inotify. So I started to write
this program with using of fanotify. However I encountered the problem, that
fanotify was unable to catch some important events atthe moment of writing the
program, like "directory creation" or "file deletion". So I switched to
"inotify", leaving the code for "fanotify" in the safety... So, don't use
"fanotify" in this utility ;).
_____________________________________________
3.) How to use
Well, let's see:
d[13:25:13] [xaionaro@linux ~/clsync]$ ./clsync
syntax: clsync [flags] <watch dir> <action script> [file with rules regexps]
possible flags:
--background -b
--pthread -p
--collectdelay -t
--commondelay -w
--outlistsdir -d
--bigfilethreshold -B
--bigfilecollectdelay -T
--verbose -v
--debug -D
--quite -q
--fanotify -f
--inotify -i
--label -l
--help -h
"watch dir" - what dir to recursively watch for events
"action script" - path to script, that will be executed to process events
"file with rules regexps" - file with regexps of what files/dirs to watch
Options with "*" requires an argument:
--background - daemonize
--pthread - use multi-threading
* --collectdelay - delay to collect events for ordinary files/dirs (def: 30)
* --commondelay - delay in addition for all queues (def: 15)
* --outlistsdir - path to directory, where clsync should temporary save his
events' lists
* --bigfilethreshold - file size theshold to mark file as big (def: 134217728)
* --bigfilecollectdelay - delay to collect events for big files (def: 1800)
--verbose - increases verbosity (doesn't do anything at the moment)
--debug - increases debug output
--quite - don't output errors
--fanotify - use "fanotify" engine instead of "inotify"
--inotify - use "inotify" engine instead of "fanotify" (def)
* --label - set label of current clsync instance
--help - output the same info as above
Now, let me explain few things:
--pthread - Should be used to watch huge file trees with high dynamics to
remove huge delays to update something due to updating something another
--collectdelay - Is way to aggregate events for ordinary files/dirs. Than this
value greater, the aggrigation will be more effective, but the sync delay will
be higher
--outlistsdir - Enables "sync by list" notification of "action script", but to
sync by list it's required a directory for temporary files (with lists of
events). So you're aggregation a lot of actions per collect-delay period,
it's need to provide it and set the path to it to this parameter.
--fanotify - Enables "fanotify" engine instead of "inotify". However
developing of "fanotify" support was been frozen at the start of this program
life, so "fanotify" doesn't work at the moment. Don't use it :)
--label - May be useful, if you're going to serve different clsync instances
by one action script
Multi-threading:
As I said, pthread is recommended for file trees with high dynamics to
minimize side-effected delays. However threading code is much more complex,
so the sum of bugs there will be much higher. If you will find some of them,
please mail me, I'll fix it :)
Delays' calculcation:
Ordinary file/dir maximum sync delay = collectdelay + commondelay
Big files maximum sync delay = bigfilecollectdelay + commondelay
Action script:
The clsync with run "action script" every time, when it will want to notify
about requirement of sync. So the "action script" should do this syncing by
this notifications.
The clsync can run "action script" with the ways:
a.) action_script initialsync label dirpath
b.) action_script sync label evmask path
c.) action_script synclist label listpath
In all three cases, clsync passes parameter "label" (the label of current,
instance, see "--label").
In case "a", clsync asks "action script" to recursivly sync the dir "dirpath".
In case 'b', clsync asks "action script" to non-recursivly sync the file/dir
"path" due to event of mask "evmask".
In case "c", clsync asks "action script" to non-recursivly sync files/dirs
from list in file "listpath".
Format of list-files:
List-files "consists" from lines (delimited by NL, without CR) of next format:
sync label evmask path
"sync" is always "sync" at the moment. It's supposed to be supported different
commands in this list, but at the moment there's only "sync" supported.
"label" is "label" (see "--label").
"evmask" is mask of the event, why the file/dir should be updated (see below).
"path" is the path of file/dir that should be updated.
Event mask:
Event mask is bitmask sum of events of the file/dir, that were been aggregated
for collect-delay. You can learn that bits in "/usr/include/linux/inotify.h".
Example:
Example of usage, that works on my PC is in directory "example". Just run
"clsync-start.sh" and try to create/modify/delete files/dirs in
"example/testdir/from". All modifications should appear (with some delay) in
directory "example/testdir/to" ;)
_____________________________________________
4.) Known issues
1.) Doesn't compiles on old systems
In this case you should fix this things:
- Remove all fanotify code from "sync.c", "main.c" and "common.c"
- Replace "gnu11" with "gnu99" in "GNUmakefile"
2.) Exits with error "Error: Cannot inotify_add_watch() on [...]"
In this case you should increase "fs.inotify.max_user_watches" value,
for example with command: sysctl fs.inotify.max_user_watches=26214400
_____________________________________________
5.) Support
To get support, you can contact with me this ways:
- IRC: SSL+UTF-8 irc.campus.mephi.ru:6695#mephi,xaionaro,xai
- e-mail: <xai@mephi.ru>, <dyokunev@ut.mephi.ru>, <xaionaro@gmail.com>
PGP pubkey: 0x8E30679C
_____________________________________________
-- Dmitry Yu Okunev <xai@mephi.ru> 0x8E30679C
P.S.: Sorry for my English and for the code :)
... ...
... ... @@ -23,7 +23,7 @@
#include "malloc.h"
// This function checks file path by rules' expressions (from file)
// Checks file path by rules' expressions (from file)
// Return: action for the "file path"
static ruleaction_t rules_check(const char *fpath, mode_t st_mode, rule_t *rules_p) {
... ... @@ -55,7 +55,7 @@ static ruleaction_t rules_check(const char *fpath, mode_t st_mode, rule_t *rules
return action;
}
// This function removes necessary rows from hash_tables if some watching descriptor closed
// Removes necessary rows from hash_tables if some watching descriptor closed
// Return: 0 on success, non-zero on fail
static inline int indexes_remove_bywd(indexes_t *indexes_p, int wd) {
... ... @@ -73,7 +73,7 @@ static inline int indexes_remove_bywd(indexes_t *indexes_p, int wd) {
return ret;
}
// This function add necessary rows to hash_tables if some watching descriptor opened
// Adds necessary rows to hash_tables if some watching descriptor opened
// Return: 0 on success, non-zero on fail
static inline int indexes_add_wd(indexes_t *indexes_p, int wd, const char *fpath_const, size_t fpathlen) {
... ... @@ -87,13 +87,15 @@ static inline int indexes_add_wd(indexes_t *indexes_p, int wd, const char *fpath
return 0;
}
// This function is lookup file path by watching descriptor from hash_tables
// Lookups file path by watching descriptor from hash_tables
// Return: file path on success, NULL on fail
static inline char *indexes_wd2fpath(indexes_t *indexes_p, int wd) {
return g_hash_table_lookup(indexes_p->wd2fpath_ht, GINT_TO_POINTER(wd));
}
//
static inline int indexes_fpath2wd(indexes_t *indexes_p, const char *fpath) {
gpointer gint_p = g_hash_table_lookup(indexes_p->fpath2wd_ht, fpath);
if(gint_p == NULL)
... ...