From: Jaroslav Kysela Date: Sat, 12 Dec 2015 20:12:42 +0000 (+0100) Subject: inotify: register fix and add support for multiple files, fixes #3416 X-Git-Tag: v4.2.1~1314 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f995c21cd7c1f9113a465989e1c860eb3e4b773c;p=thirdparty%2Ftvheadend.git inotify: register fix and add support for multiple files, fixes #3416 --- diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 8dd4d2344..f4ec7dec3 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -265,13 +265,6 @@ typedef struct dvr_entry { */ profile_chain_t *de_chain; - /** - * Inotify - */ -#if ENABLE_INOTIFY - LIST_ENTRY(dvr_entry) de_inotify_link; -#endif - /** * Entry change notification timer */ diff --git a/src/dvr/dvr_inotify.c b/src/dvr/dvr_inotify.c index 87ed4b0a4..c9ad3682f 100644 --- a/src/dvr/dvr_inotify.c +++ b/src/dvr/dvr_inotify.c @@ -16,7 +16,8 @@ * along with this program. If not, see . */ -#include +#include "tvheadend.h" + #include #include #include @@ -25,7 +26,6 @@ #include #include -#include "tvheadend.h" #include "redblack.h" #include "dvr/dvr.h" #include "htsp_server.h" @@ -39,12 +39,18 @@ static int _inot_fd; static RB_HEAD(,dvr_inotify_entry) _inot_tree; +typedef struct dvr_inotify_filename +{ + dvr_entry_t *de; + LIST_ENTRY(dvr_inotify_filename) link; +} dvr_inotify_filename_t; + typedef struct dvr_inotify_entry { RB_ENTRY(dvr_inotify_entry) link; - char *path; - int fd; - struct dvr_entry_list entries; + char *path; + int fd; + LIST_HEAD(, dvr_inotify_filename) entries; } dvr_inotify_entry_t; static SKEL_DECLARE(dvr_inotify_entry_skel, dvr_inotify_entry_t); @@ -87,46 +93,73 @@ void dvr_inotify_done ( void ) SKEL_FREE(dvr_inotify_entry_skel); } +/** + * + */ +static int dvr_inotify_exists ( dvr_inotify_entry_t *die, dvr_entry_t *de ) +{ + dvr_inotify_filename_t *dif; + + LIST_FOREACH(dif, &die->entries, link) + if (dif->de == de) + return 1; + return 0; +} + /** * Add an entry for monitoring */ -void dvr_inotify_add ( dvr_entry_t *de ) +static void dvr_inotify_add_one ( dvr_entry_t *de, htsmsg_t *m ) { + dvr_inotify_filename_t *dif; dvr_inotify_entry_t *e; - const char *filename = dvr_get_filename(de); + const char *filename; char *path; - if (_inot_fd < 0) - return; - + filename = htsmsg_get_str(m, "filename"); if (filename == NULL) return; - path = strdup(filename); + path = strdupa(filename); SKEL_ALLOC(dvr_inotify_entry_skel); dvr_inotify_entry_skel->path = dirname(path); e = RB_INSERT_SORTED(&_inot_tree, dvr_inotify_entry_skel, link, _str_cmp); - if (e) { - free(path); - return; + if (!e) { + e = dvr_inotify_entry_skel; + SKEL_USED(dvr_inotify_entry_skel); + e->path = strdup(e->path); + e->fd = inotify_add_watch(_inot_fd, e->path, EVENT_MASK); } - e = dvr_inotify_entry_skel; - SKEL_USED(dvr_inotify_entry_skel); - e->path = strdup(e->path); - e->fd = inotify_add_watch(_inot_fd, e->path, EVENT_MASK); + if (!dvr_inotify_exists(e, de)) { - LIST_INSERT_HEAD(&e->entries, de, de_inotify_link); + dif = malloc(sizeof(*dif)); + dif->de = de; + + LIST_INSERT_HEAD(&e->entries, dif, link); + + if (e->fd < 0) { + tvhlog(LOG_ERR, "dvr", "failed to add inotify watch to %s (err=%s)", + e->path, strerror(errno)); + dvr_inotify_del(de); + } - if (e->fd < 0) { - tvhlog(LOG_ERR, "dvr", "failed to add inotify watch to %s (err=%s)", - e->path, strerror(errno)); - dvr_inotify_del(de); } +} + +void dvr_inotify_add ( dvr_entry_t *de ) +{ + htsmsg_field_t *f; + htsmsg_t *m; - free(path); + if (_inot_fd < 0) + return; + + HTSMSG_FOREACH(f, de->de_files) + if ((m = htsmsg_field_get_map(f)) != NULL) + dvr_inotify_add_one(de, m); } /* @@ -134,23 +167,25 @@ void dvr_inotify_add ( dvr_entry_t *de ) */ void dvr_inotify_del ( dvr_entry_t *de ) { - dvr_entry_t *det = NULL; - dvr_inotify_entry_t *e; + dvr_inotify_filename_t *f = NULL, *f_next; + dvr_inotify_entry_t *e, *e_next; lock_assert(&global_lock); - RB_FOREACH(e, &_inot_tree, link) { - LIST_FOREACH(det, &e->entries, de_inotify_link) - if (det == de) break; - if (det) break; - } - if (e && det) { - LIST_REMOVE(det, de_inotify_link); - if (LIST_FIRST(&e->entries) == NULL) { - RB_REMOVE(&_inot_tree, e, link); - if (e->fd >= 0) - inotify_rm_watch(_inot_fd, e->fd); - free(e->path); - free(e); + for (e = RB_FIRST(&_inot_tree); e; e = e_next) { + e_next = RB_NEXT(e, link); + for (f = LIST_FIRST(&e->entries); f; f = f_next) { + f_next = LIST_NEXT(f, link); + if (f->de == de) { + LIST_REMOVE(f, link); + free(f); + if (LIST_FIRST(&e->entries) == NULL) { + RB_REMOVE(&_inot_tree, e, link); + if (e->fd >= 0) + inotify_rm_watch(_inot_fd, e->fd); + free(e->path); + free(e); + } + } } } } @@ -160,12 +195,12 @@ void dvr_inotify_del ( dvr_entry_t *de ) */ int dvr_inotify_count ( void ) { - dvr_entry_t *det = NULL; + dvr_inotify_filename_t *f; dvr_inotify_entry_t *e; int count = 0; lock_assert(&global_lock); RB_FOREACH(e, &_inot_tree, link) - LIST_FOREACH(det, &e->entries, de_inotify_link) + LIST_FOREACH(f, &e->entries, link) count++; return count; } @@ -191,6 +226,7 @@ static void _dvr_inotify_moved ( int fd, const char *from, const char *to ) { + dvr_inotify_filename_t *dif; dvr_inotify_entry_t *die; dvr_entry_t *de; char path[PATH_MAX]; @@ -203,7 +239,8 @@ _dvr_inotify_moved snprintf(path, sizeof(path), "%s/%s", die->path, from); - LIST_FOREACH(de, &die->entries, de_inotify_link) { + LIST_FOREACH(dif, &die->entries, link) { + de = dif->de; if (de->de_files == NULL) continue; HTSMSG_FOREACH(f, de->de_files) @@ -216,7 +253,7 @@ _dvr_inotify_moved break; } - if (!de) + if (!dif) return; if (f && m) { @@ -253,13 +290,15 @@ static void _dvr_inotify_moved_all ( int fd, const char *to ) { - dvr_entry_t *de; + dvr_inotify_filename_t *f; dvr_inotify_entry_t *die; + dvr_entry_t *de; if (!(die = _dvr_inotify_find(fd))) return; - while ((de = LIST_FIRST(&die->entries))) { + while ((f = LIST_FIRST(&die->entries))) { + de = f->de; htsp_dvr_entry_update(de); idnode_notify_changed(&de->de_id); dvr_inotify_del(de);