* 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>
#include <sys/inotify.h>
#include <sys/stat.h>
-#include "tvheadend.h"
#include "redblack.h"
#include "dvr/dvr.h"
#include "htsp_server.h"
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);
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);
}
/*
*/
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);
+ }
+ }
}
}
}
*/
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;
}
_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];
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)
break;
}
- if (!de)
+ if (!dif)
return;
if (f && m) {
_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);