libresman

view src/filewatch_linux.c @ 23:f8e5a1491275

win32 file change notification attempt1 (failed)
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 13 Feb 2014 13:17:07 +0200
parents 174ddb6bf92a
children
line source
1 /* file modification monitoring with inotify */
2 #ifdef __linux__
3 #include <stdio.h>
4 #include <assert.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/inotify.h>
8 #include "filewatch.h"
9 #include "resman.h"
10 #include "resman_impl.h"
12 static void reload_modified(struct rbnode *node, void *cls);
14 int resman_init_file_monitor(struct resman *rman)
15 {
16 int fd;
18 if((fd = inotify_init()) == -1) {
19 return -1;
20 }
21 /* set non-blocking flag, to allow polling by reading */
22 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
23 rman->inotify_fd = fd;
25 /* create the fd->resource map */
26 rman->nresmap = rb_create(RB_KEY_INT);
27 /* create the modified set */
28 rman->modset = rb_create(RB_KEY_INT);
29 return 0;
30 }
32 void resman_destroy_file_monitor(struct resman *rman)
33 {
34 rb_free(rman->nresmap);
35 rb_free(rman->modset);
37 if(rman->inotify_fd >= 0) {
38 close(rman->inotify_fd);
39 rman->inotify_fd = -1;
40 }
41 }
43 int resman_start_watch(struct resman *rman, struct resource *res)
44 {
45 int fd;
47 if(res->nfd > 0) {
48 return 0; /* already started a watch for this resource */
49 }
51 if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) {
52 return -1;
53 }
54 printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd);
55 rb_inserti(rman->nresmap, fd, res);
57 res->nfd = fd;
58 return 0;
59 }
61 void resman_stop_watch(struct resman *rman, struct resource *res)
62 {
63 if(res->nfd > 0) {
64 rb_deletei(rman->nresmap, res->nfd);
65 inotify_rm_watch(rman->inotify_fd, res->nfd);
66 }
67 }
69 void resman_check_watch(struct resman *rman)
70 {
71 char buf[512];
72 struct inotify_event *ev;
73 int sz, evsize;
75 while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) {
76 ev = (struct inotify_event*)buf;
77 while(sz > 0) {
78 if(ev->mask & IN_MODIFY) {
79 /* add the file descriptor to the modified set */
80 rb_inserti(rman->modset, ev->wd, 0);
81 }
83 evsize = sizeof *ev + ev->len;
84 sz -= evsize;
85 ev += evsize;
86 }
87 }
89 /* for each item in the modified set, start a new job to reload it */
90 rb_foreach(rman->modset, reload_modified, rman);
91 rb_clear(rman->modset);
92 }
94 /* this is called for each item in the modified set (see above) */
95 static void reload_modified(struct rbnode *node, void *cls)
96 {
97 int watch_fd;
98 struct resource *res;
99 struct resman *rman = cls;
101 watch_fd = rb_node_keyi(node);
103 if(!(res = rb_findi(rman->nresmap, watch_fd))) {
104 fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n",
105 __FUNCTION__, watch_fd);
106 return;
107 }
108 assert(watch_fd == res->nfd);
110 printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node));
112 tpool_add_work(rman->tpool, res);
113 }
115 #else
116 int resman_filewatch_linux_silence_empty_file_warning;
117 #endif /* __linux__ */