mirror of
https://github.com/octoleo/lsyncd.git
synced 2025-01-06 08:40:44 +00:00
parent pointers
This commit is contained in:
parent
414a426452
commit
49e7f3aa0d
180
lsyncd.c
180
lsyncd.c
@ -189,10 +189,9 @@ struct watch {
|
||||
char * dirname;
|
||||
|
||||
/**
|
||||
* Points to the index of the parent.
|
||||
* -1 if no parent
|
||||
* Points to the parent. NULL if no parent.
|
||||
*/
|
||||
int parent;
|
||||
struct watch *parent;
|
||||
|
||||
/**
|
||||
* On a delay to be handled.
|
||||
@ -756,16 +755,29 @@ dir_conf_add_target(const struct log *log, struct dir_conf *dir_conf, char *targ
|
||||
* @param alarm times() when the directory should be acted
|
||||
*/
|
||||
bool
|
||||
append_delay(const struct log *log, struct watch_vector *watches, int watch, clock_t alarm) {
|
||||
printlogf(log, DEBUG, "append delay(%d)", watch);
|
||||
if (watches->data[watch]->delayed) {
|
||||
printlogf(log, DEBUG, "ignored since already delayed.", watch);
|
||||
append_delay(const struct log *log,
|
||||
struct watch_vector *watches, // TODO?
|
||||
struct watch *watch,
|
||||
clock_t alarm)
|
||||
{
|
||||
printlogf(log, DEBUG, "append delay(%s, %d)", watch->dirname, alarm);
|
||||
if (watch->delayed) {
|
||||
printlogf(log, DEBUG, "ignored since already delayed.");
|
||||
return false;
|
||||
}
|
||||
watches->data[watch]->delayed = true;
|
||||
watches->data[watch]->alarm = alarm;
|
||||
watch->delayed = true;
|
||||
watch->alarm = alarm;
|
||||
|
||||
ivector_push(log, delays, watch);
|
||||
{
|
||||
// TODO remove this
|
||||
int i;
|
||||
for(i = 0; i < watches->len; i++) {
|
||||
if(watches->data[i] == watch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ivector_push(log, delays, i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -987,16 +999,16 @@ action(const struct global_options *opts,
|
||||
* @param parent if not -1 the index to the parent directory that is already watched
|
||||
* @param dir_conf the applicateable configuration
|
||||
*
|
||||
* @return index to watches of the new dir, -1 on error.
|
||||
* @return the watches of the new dir, NULL on error
|
||||
*/
|
||||
int
|
||||
struct watch *
|
||||
add_watch(const struct log *log,
|
||||
struct watch_vector *watches,
|
||||
int inotify_fd,
|
||||
char const * pathname,
|
||||
char const * dirname,
|
||||
int parent,
|
||||
struct dir_conf * dir_conf)
|
||||
char const *pathname,
|
||||
char const *dirname,
|
||||
struct watch *parent,
|
||||
struct dir_conf *dir_conf)
|
||||
{
|
||||
int wd; // kernels inotify descriptor
|
||||
int newdw; // position to insert this watch into the watch vector
|
||||
@ -1009,7 +1021,7 @@ add_watch(const struct log *log,
|
||||
if (wd == -1) {
|
||||
printlogf(log, ERROR, "Cannot add watch %s (%d:%s)",
|
||||
pathname, errno, strerror(errno));
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// look if an unused slot can be found.
|
||||
@ -1034,22 +1046,23 @@ add_watch(const struct log *log,
|
||||
watches->data[watches->len++] = s_calloc(log, 1, sizeof(struct watch));
|
||||
}
|
||||
|
||||
// TODO simplify using pointer
|
||||
watches->data[newdw]->wd = wd;
|
||||
watches->data[newdw]->parent = parent;
|
||||
watches->data[newdw]->dirname = s_strdup(log, dirname);
|
||||
watches->data[newdw]->dir_conf = dir_conf;
|
||||
watches->data[newdw]->alarm = 0; // not needed, just to be save
|
||||
watches->data[newdw]->delayed = false;
|
||||
return newdw;
|
||||
return watches->data[newdw];
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the path of a watched directory into pathname.
|
||||
*
|
||||
* @param pathname path to write to
|
||||
* @param pathsize size of the pathname buffer
|
||||
* @param watch index of watched dir to build path for
|
||||
* @param prefix replace root dir with this (as target)
|
||||
* @param pathname path to write to
|
||||
* @param pathsize size of the pathname buffer
|
||||
* @param watch watched dir to build path for
|
||||
* @param prefix replace root dir with this (as target)
|
||||
*
|
||||
* @return -1 if pathname buffer was too small
|
||||
* contents of pathname will be garbled then.
|
||||
@ -1059,21 +1072,21 @@ int
|
||||
builddir(char *pathname,
|
||||
int pathsize,
|
||||
struct watch_vector *watches, //TODO remove and change to pointer
|
||||
int watch,
|
||||
char const * prefix)
|
||||
struct watch *watch,
|
||||
char const *prefix)
|
||||
{
|
||||
int len = 0;
|
||||
if (watch == -1) {
|
||||
// TODO When is this called this way???
|
||||
if (!watch) {
|
||||
// TODO Is this ever called?
|
||||
char const * p = prefix ? prefix : "";
|
||||
len = strlen(p);
|
||||
if (pathsize <= len) {
|
||||
return -1;
|
||||
}
|
||||
strcpy(pathname, p);
|
||||
} else if (watches->data[watch]->parent == -1) {
|
||||
} else if (!watch->parent) {
|
||||
// this is a watch root.
|
||||
char const * p = prefix ? prefix : watches->data[watch]->dirname;
|
||||
char const * p = prefix ? prefix : watch->dirname;
|
||||
len = strlen(p);
|
||||
if (pathsize <= len) {
|
||||
return -1;
|
||||
@ -1081,12 +1094,12 @@ builddir(char *pathname,
|
||||
strcpy(pathname, p);
|
||||
} else {
|
||||
// this is some sub dir
|
||||
len = builddir(pathname, pathsize, watches, watches->data[watch]->parent, prefix); /* recurse */
|
||||
len += strlen(watches->data[watch]->dirname);
|
||||
len = builddir(pathname, pathsize, watches, watch->parent, prefix); /* recurse */
|
||||
len += strlen(watch->dirname);
|
||||
if (pathsize <= len) {
|
||||
return -1;
|
||||
}
|
||||
strcat(pathname, watches->data[watch]->dirname);
|
||||
strcat(pathname, watch->dirname);
|
||||
}
|
||||
// add the trailing slash if it is missing
|
||||
if (*pathname && pathname[strlen(pathname)-1] != '/') {
|
||||
@ -1102,7 +1115,7 @@ builddir(char *pathname,
|
||||
*
|
||||
* @param pathname destination buffer to store the result to.
|
||||
* @param pathsize max size of this buffer
|
||||
* @param watch the index in watches to the directory.
|
||||
* @param watch the watches of the directory.
|
||||
* @param dirname if not NULL it is added at the end of pathname
|
||||
* @param prefix if not NULL it is added at the beginning of pathname
|
||||
*/
|
||||
@ -1111,7 +1124,7 @@ buildpath(const struct log *log,
|
||||
char *pathname,
|
||||
int pathsize,
|
||||
struct watch_vector *watches, // TODO remove need
|
||||
int watch,
|
||||
struct watch *watch,
|
||||
const char *dirname,
|
||||
const char *prefix)
|
||||
{
|
||||
@ -1127,7 +1140,6 @@ buildpath(const struct log *log,
|
||||
}
|
||||
strcat(pathname, dirname);
|
||||
}
|
||||
printlogf(log, DEBUG, " BUILDPATH(%d, %s, %s) -> %s", watch, dirname, prefix, pathname);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1137,14 +1149,14 @@ buildpath(const struct log *log,
|
||||
* directory gone away, and thus cannot work, or network
|
||||
* failed)
|
||||
*
|
||||
* @param watch the index in watches to the directory.
|
||||
* @param watch the watch of the directory.
|
||||
*
|
||||
* @returns true when all targets were successful.
|
||||
*/
|
||||
bool
|
||||
rsync_dir(const struct global_options *opts,
|
||||
struct watch_vector *watches, // TODO remove
|
||||
int watch)
|
||||
struct watch *watch)
|
||||
{
|
||||
char pathname[PATH_MAX+1];
|
||||
char destname[PATH_MAX+1];
|
||||
@ -1156,7 +1168,7 @@ rsync_dir(const struct global_options *opts,
|
||||
return false;
|
||||
}
|
||||
|
||||
for (target = watches->data[watch]->dir_conf->targets; *target; target++) {
|
||||
for (target = watch->dir_conf->targets; *target; target++) {
|
||||
if (!buildpath(log, destname, sizeof(destname), watches, watch, NULL, *target)) {
|
||||
status = false;
|
||||
continue;
|
||||
@ -1164,7 +1176,7 @@ rsync_dir(const struct global_options *opts,
|
||||
printlogf(log, NORMAL, "rsyncing %s --> %s", pathname, destname);
|
||||
|
||||
// call rsync to propagate changes in the directory
|
||||
if (!action(opts, watches->data[watch]->dir_conf, pathname, destname, false)) {
|
||||
if (!action(opts, watch->dir_conf, pathname, destname, false)) {
|
||||
printlogf(log, ERROR, "Rsync from %s to %s failed", pathname, destname);
|
||||
status = false;
|
||||
}
|
||||
@ -1182,7 +1194,7 @@ rsync_dir(const struct global_options *opts,
|
||||
void
|
||||
delay_dir(const struct global_options *opts,
|
||||
struct watch_vector *watches, //TODO remove?
|
||||
int watch,
|
||||
struct watch *watch,
|
||||
clock_t alarm)
|
||||
{
|
||||
char pathname[PATH_MAX+1];
|
||||
@ -1216,27 +1228,27 @@ delay_dir(const struct global_options *opts,
|
||||
* Must have absolute path if parent == -1.
|
||||
* @param dir_conf ??? TODO
|
||||
*
|
||||
* @returns the index in watches of the directory or -1 on fail.
|
||||
* @returns the watches of the directory or NULL on fail.
|
||||
*/
|
||||
int
|
||||
struct watch *
|
||||
add_dirwatch(const struct global_options *opts,
|
||||
struct watch_vector *watches,
|
||||
int inotify_fd,
|
||||
char const *dirname,
|
||||
int parent,
|
||||
struct watch *parent,
|
||||
struct dir_conf *dir_conf)
|
||||
{
|
||||
const struct log *log = &opts->log;
|
||||
DIR *d;
|
||||
int dw;
|
||||
struct watch *dw; // TODO rename
|
||||
char pathname[PATH_MAX+1];
|
||||
|
||||
printlogf(log, DEBUG, "add_dirwatch(%s, p->dirname:%s, ...)",
|
||||
dirname,
|
||||
parent >= 0 ? watches->data[parent]->dirname : "NULL");
|
||||
parent ? parent->dirname : "NULL");
|
||||
|
||||
if (!buildpath(log, pathname, sizeof(pathname), watches, parent, dirname, NULL)) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
@ -1244,7 +1256,7 @@ add_dirwatch(const struct global_options *opts,
|
||||
for (i = 0; i < exclude_dir_n; i++) {
|
||||
if (!strcmp(pathname, exclude_dirs[i])) {
|
||||
printlogf(log, NORMAL, "Excluded %s", pathname);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
printlogf(log, DEBUG, "comparing %s with %s not an exclude so far.", pathname, exclude_dirs[i]);
|
||||
}
|
||||
@ -1252,8 +1264,8 @@ add_dirwatch(const struct global_options *opts,
|
||||
|
||||
// watch this directory
|
||||
dw = add_watch(log, watches, inotify_fd, pathname, dirname, parent, dir_conf);
|
||||
if (dw == -1) {
|
||||
return -1;
|
||||
if (!dw) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// put this directory on list to be synced ASAP.
|
||||
@ -1261,13 +1273,13 @@ add_dirwatch(const struct global_options *opts,
|
||||
|
||||
if (strlen(pathname) + strlen(dirname) + 2 > sizeof(pathname)) {
|
||||
printlogf(log, ERROR, "pathname too long %s//%s", pathname, dirname);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d = opendir(pathname);
|
||||
if (d == NULL) {
|
||||
printlogf(log, ERROR, "cannot open dir %s.", dirname);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (keep_going) { // terminate early on KILL signal
|
||||
@ -1295,11 +1307,12 @@ add_dirwatch(const struct global_options *opts,
|
||||
|
||||
// add watches if its a directory and not . or ..
|
||||
if (isdir && strcmp(de->d_name, "..") && strcmp(de->d_name, ".")) {
|
||||
// recurse into subdir
|
||||
int ndw = add_dirwatch(opts, watches, inotify_fd, de->d_name, dw, dir_conf);
|
||||
// recurse into subdirectories
|
||||
// TODO rename
|
||||
struct watch *ndw = add_dirwatch(opts, watches, inotify_fd, de->d_name, dw, dir_conf);
|
||||
printlogf(log, NORMAL,
|
||||
"found new directory: %s in %s -- %s",
|
||||
de->d_name, dirname, ndw >= 0 ? "will be synced" : "ignored it");
|
||||
de->d_name, dirname, ndw ? "will be synced" : "ignored it");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1315,7 +1328,7 @@ add_dirwatch(const struct global_options *opts,
|
||||
* @param inotify_fd inotify file descriptor
|
||||
* @param name optionally. If not NULL, the directory name
|
||||
* to remove which is a child of parent
|
||||
* @param parent the index to the parent directory of the
|
||||
* @param parent the parent directory of the
|
||||
* directory 'name' to remove, or to be removed
|
||||
* itself if name == NULL.
|
||||
*/
|
||||
@ -1324,24 +1337,25 @@ remove_dirwatch(const struct global_options *opts,
|
||||
struct watch_vector *watches,
|
||||
int inotify_fd,
|
||||
const char * name,
|
||||
int parent)
|
||||
struct watch *parent)
|
||||
{
|
||||
const struct log *log = &opts->log;
|
||||
int dw; // the directory index to remove.
|
||||
struct watch *dw; // the directory to remove -> TODO rename
|
||||
if (name) {
|
||||
int i;
|
||||
// look for the child with the name
|
||||
// TODO optimize by using subdir lists
|
||||
for (i = 0; i < watches->len; i++) {
|
||||
struct watch *p = watches->data[i];
|
||||
if (p->wd >= 0 && p->parent == parent && !strcmp(name, p->dirname)) {
|
||||
dw = i;
|
||||
dw = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= watches->len) {
|
||||
printlogf(log, ERROR, "Cannot find entry for %s:/:%s :-(",
|
||||
watches->data[parent]->dirname, name);
|
||||
parent->dirname, name);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -1350,28 +1364,29 @@ remove_dirwatch(const struct global_options *opts,
|
||||
|
||||
{
|
||||
// recurse into all subdirectories removing them.
|
||||
// TODO possible optimization by keeping a list of subdirs
|
||||
int i;
|
||||
for (i = 0; i < watches->len; i++) {
|
||||
// TODO shortcut pointer
|
||||
if (watches->data[i]->wd >= 0 && watches->data[i]->parent == dw) {
|
||||
remove_dirwatch(opts, watches, inotify_fd, NULL, i);
|
||||
remove_dirwatch(opts, watches, inotify_fd, NULL, watches->data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inotify_rm_watch(inotify_fd, watches->data[dw]->wd);
|
||||
// mark this entry invalid (cannot remove, since indexes point into this vector)
|
||||
// (TODO Currently parents and watches)
|
||||
watches->data[dw]->wd = -1;
|
||||
inotify_rm_watch(inotify_fd, dw->wd);
|
||||
// mark this entry invalid
|
||||
dw->wd = -1;
|
||||
|
||||
free(watches->data[dw]->dirname);
|
||||
watches->data[dw]->dirname = NULL;
|
||||
free(dw->dirname);
|
||||
dw->dirname = NULL;
|
||||
|
||||
// remove a possible delay
|
||||
// (this dir is on the to do/delay list)
|
||||
if (delays->len > 0 && watches->data[dw]->delayed) {
|
||||
if (delays->len > 0 && dw->delayed) {
|
||||
int i;
|
||||
for(i = 0; i < delays->len; i++) {
|
||||
if (delays->data[i] == dw) {
|
||||
if (watches->data[delays->data[i]] == dw) { // TODO delay pointers
|
||||
// move the list up.
|
||||
memmove(delays->data + i, delays->data + i + 1, (delays->len - i - 1) * sizeof(int));
|
||||
delays->len--;
|
||||
@ -1384,23 +1399,24 @@ remove_dirwatch(const struct global_options *opts,
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the matching dw entry containing a watch descriptor
|
||||
* and return its offset.
|
||||
* Find the matching watch descriptor
|
||||
*
|
||||
* @param watches the watch vector
|
||||
* @param wd the wd (watch descriptor) given by inotify
|
||||
*
|
||||
* @return offset, or -1 if not found
|
||||
* @return the watch or NULL if not found
|
||||
*/
|
||||
int
|
||||
get_watch_offset(const struct watch_vector *watches, int wd) {
|
||||
struct watch *
|
||||
get_watch(const struct watch_vector *watches,
|
||||
int wd)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < watches->len; i++) {
|
||||
if (watches->data[i]->wd == wd) {
|
||||
return i;
|
||||
return watches->data[i];
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1421,9 +1437,9 @@ handle_event(const struct global_options *opts,
|
||||
{
|
||||
char masktext[255] = {0,};
|
||||
int mask = event->mask;
|
||||
int i, watch;
|
||||
int subwatch = -1;
|
||||
struct inotify_mask_text *p;
|
||||
int i; //TODO
|
||||
struct inotify_mask_text *p; //TODO
|
||||
struct watch *watch;
|
||||
const struct log *log = &opts->log;
|
||||
|
||||
// creates a string for logging that shows which flags
|
||||
@ -1455,8 +1471,8 @@ handle_event(const struct global_options *opts,
|
||||
}
|
||||
}
|
||||
|
||||
watch = get_watch_offset(watches, event->wd);
|
||||
if (watch == -1) {
|
||||
watch = get_watch(watches, event->wd);
|
||||
if (!watch) {
|
||||
// this can happen in case of data moving faster than lsyncd can monitor it.
|
||||
printlogf(log, NORMAL,
|
||||
"received an inotify event that doesnt match any watched directory.");
|
||||
@ -1465,7 +1481,7 @@ handle_event(const struct global_options *opts,
|
||||
|
||||
// in case of a new directory create new watches
|
||||
if (((IN_CREATE | IN_MOVED_TO) & event->mask) && (IN_ISDIR & event->mask)) {
|
||||
subwatch = add_dirwatch(opts, watches, inotify_fd, event->name, watch, watches->data[watch]->dir_conf);
|
||||
add_dirwatch(opts, watches, inotify_fd, event->name, watch, watch->dir_conf);
|
||||
}
|
||||
|
||||
// in case of a removed directory remove watches
|
||||
@ -1587,7 +1603,7 @@ master_loop(const struct global_options *opts,
|
||||
// again as time may progresses while handling delayed entries.
|
||||
while (delays->len > 0 && time_after_eq(times(NULL), watches->data[delays->data[0]]->alarm)) {
|
||||
printlogf(log, DEBUG, "time for %d arrived.", delays->data[0]);
|
||||
rsync_dir(opts, watches, delays->data[0]);
|
||||
rsync_dir(opts, watches, watches->data[delays->data[0]]); // TODO
|
||||
remove_first_delay(watches);
|
||||
}
|
||||
}
|
||||
@ -2291,7 +2307,7 @@ main(int argc, char **argv)
|
||||
int i;
|
||||
for (i = 0; i < opts.dir_conf_n; i++) {
|
||||
printlogf(log, NORMAL, "watching %s", opts.dir_confs[i].source);
|
||||
add_dirwatch(&opts, &watches, inotify_fd, opts.dir_confs[i].source, -1, &opts.dir_confs[i]);
|
||||
add_dirwatch(&opts, &watches, inotify_fd, opts.dir_confs[i].source, NULL, &opts.dir_confs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user