Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
inotify: register fix and add support for multiple files, fixes #3416
  • Loading branch information
perexg committed Dec 12, 2015
1 parent 676a34f commit f995c21
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 52 deletions.
7 changes: 0 additions & 7 deletions src/dvr/dvr.h
Expand Up @@ -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
*/
Expand Down
129 changes: 84 additions & 45 deletions src/dvr/dvr_inotify.c
Expand Up @@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <string.h>
#include "tvheadend.h"

#include <unistd.h>
#include <assert.h>
#include <poll.h>
Expand All @@ -25,7 +26,6 @@
#include <sys/inotify.h>
#include <sys/stat.h>

#include "tvheadend.h"
#include "redblack.h"
#include "dvr/dvr.h"
#include "htsp_server.h"
Expand All @@ -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);
Expand Down Expand Up @@ -87,70 +93,99 @@ 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);
}

/*
* Delete an entry from the monitor
*/
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);
}
}
}
}
}
Expand All @@ -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;
}
Expand All @@ -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];
Expand All @@ -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)
Expand All @@ -216,7 +253,7 @@ _dvr_inotify_moved
break;
}

if (!de)
if (!dif)
return;

if (f && m) {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit f995c21

Please sign in to comment.