libresman
changeset 22:174ddb6bf92a
separated platform-specific filewatch code
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 12 Feb 2014 22:32:30 +0200 |
parents | fe0dbdfbe403 |
children | f8e5a1491275 |
files | src/filewatch.h src/filewatch_linux.c src/filewatch_win32.c src/resman.c src/resman_impl.h |
diffstat | 5 files changed, 308 insertions(+), 162 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/filewatch.h Wed Feb 12 22:32:30 2014 +0200 1.3 @@ -0,0 +1,15 @@ 1.4 +#ifndef FILEWATCH_H_ 1.5 +#define FILEWATCH_H_ 1.6 + 1.7 +struct resman; 1.8 +struct resource; 1.9 + 1.10 +int resman_init_file_monitor(struct resman *rman); 1.11 +void resman_destroy_file_monitor(struct resman *rman); 1.12 + 1.13 +int resman_start_watch(struct resman *rman, struct resource *res); 1.14 +void resman_stop_watch(struct resman *rman, struct resource *res); 1.15 + 1.16 +void resman_check_watch(struct resman *rman); 1.17 + 1.18 +#endif /* FILEWATCH_H_ */
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/filewatch_linux.c Wed Feb 12 22:32:30 2014 +0200 2.3 @@ -0,0 +1,113 @@ 2.4 +/* file modification monitoring with inotify */ 2.5 +#ifdef __linux__ 2.6 +#include <stdio.h> 2.7 +#include <assert.h> 2.8 +#include <unistd.h> 2.9 +#include <fcntl.h> 2.10 +#include <sys/inotify.h> 2.11 +#include "filewatch.h" 2.12 +#include "resman.h" 2.13 +#include "resman_impl.h" 2.14 + 2.15 +static void reload_modified(struct rbnode *node, void *cls); 2.16 + 2.17 +int resman_init_file_monitor(struct resman *rman) 2.18 +{ 2.19 + int fd; 2.20 + 2.21 + if((fd = inotify_init()) == -1) { 2.22 + return -1; 2.23 + } 2.24 + /* set non-blocking flag, to allow polling by reading */ 2.25 + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 2.26 + rman->inotify_fd = fd; 2.27 + 2.28 + /* create the fd->resource map */ 2.29 + rman->nresmap = rb_create(RB_KEY_INT); 2.30 + /* create the modified set */ 2.31 + rman->modset = rb_create(RB_KEY_INT); 2.32 + return 0; 2.33 +} 2.34 + 2.35 +void resman_destroy_file_monitor(struct resman *rman) 2.36 +{ 2.37 + rb_free(rman->nresmap); 2.38 + rb_free(rman->modset); 2.39 + 2.40 + if(rman->inotify_fd >= 0) { 2.41 + close(rman->inotify_fd); 2.42 + rman->inotify_fd = -1; 2.43 + } 2.44 +} 2.45 + 2.46 +int resman_start_watch(struct resman *rman, struct resource *res) 2.47 +{ 2.48 + int fd; 2.49 + 2.50 + if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { 2.51 + return -1; 2.52 + } 2.53 + printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); 2.54 + rb_inserti(rman->nresmap, fd, res); 2.55 + 2.56 + res->nfd = fd; 2.57 + return 0; 2.58 +} 2.59 + 2.60 +void resman_stop_watch(struct resman *rman, struct resource *res) 2.61 +{ 2.62 + if(res->nfd > 0) { 2.63 + rb_deletei(rman->nresmap, res->nfd); 2.64 + inotify_rm_watch(rman->inotify_fd, res->nfd); 2.65 + } 2.66 +} 2.67 + 2.68 +void resman_check_watch(struct resman *rman) 2.69 +{ 2.70 + char buf[512]; 2.71 + struct inotify_event *ev; 2.72 + int sz, evsize; 2.73 + 2.74 + while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { 2.75 + ev = (struct inotify_event*)buf; 2.76 + while(sz > 0) { 2.77 + if(ev->mask & IN_MODIFY) { 2.78 + /* add the file descriptor to the modified set */ 2.79 + rb_inserti(rman->modset, ev->wd, 0); 2.80 + } 2.81 + 2.82 + evsize = sizeof *ev + ev->len; 2.83 + sz -= evsize; 2.84 + ev += evsize; 2.85 + } 2.86 + } 2.87 + 2.88 + /* for each item in the modified set, start a new job to reload it */ 2.89 + rb_foreach(rman->modset, reload_modified, rman); 2.90 + rb_clear(rman->modset); 2.91 +} 2.92 + 2.93 +/* this is called for each item in the modified set (see above) */ 2.94 +static void reload_modified(struct rbnode *node, void *cls) 2.95 +{ 2.96 + int watch_fd; 2.97 + struct resource *res; 2.98 + struct resman *rman = cls; 2.99 + 2.100 + watch_fd = rb_node_keyi(node); 2.101 + 2.102 + if(!(res = rb_findi(rman->nresmap, watch_fd))) { 2.103 + fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", 2.104 + __FUNCTION__, watch_fd); 2.105 + return; 2.106 + } 2.107 + assert(watch_fd == res->nfd); 2.108 + 2.109 + printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); 2.110 + 2.111 + tpool_add_work(rman->tpool, res); 2.112 +} 2.113 + 2.114 +#else 2.115 +int resman_filewatch_linux_silence_empty_file_warning; 2.116 +#endif /* __linux__ */
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/filewatch_win32.c Wed Feb 12 22:32:30 2014 +0200 3.3 @@ -0,0 +1,113 @@ 3.4 +/* file modification monitoring for windows */ 3.5 +#ifdef WIN32 3.6 +#include <stdio.h> 3.7 +#include <assert.h> 3.8 +#include <unistd.h> 3.9 +#include <fcntl.h> 3.10 +#include <sys/inotify.h> 3.11 +#include "filewatch.h" 3.12 +#include "resman.h" 3.13 +#include "resman_impl.h" 3.14 + 3.15 +static void reload_modified(struct rbnode *node, void *cls); 3.16 + 3.17 +int resman_init_file_monitor(struct resman *rman) 3.18 +{ 3.19 + int fd; 3.20 + 3.21 + if((fd = inotify_init()) == -1) { 3.22 + return -1; 3.23 + } 3.24 + /* set non-blocking flag, to allow polling by reading */ 3.25 + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 3.26 + rman->inotify_fd = fd; 3.27 + 3.28 + /* create the fd->resource map */ 3.29 + rman->nresmap = rb_create(RB_KEY_INT); 3.30 + /* create the modified set */ 3.31 + rman->modset = rb_create(RB_KEY_INT); 3.32 + return 0; 3.33 +} 3.34 + 3.35 +void resman_destroy_file_monitor(struct resman *rman) 3.36 +{ 3.37 + rb_free(rman->nresmap); 3.38 + rb_free(rman->modset); 3.39 + 3.40 + if(rman->inotify_fd >= 0) { 3.41 + close(rman->inotify_fd); 3.42 + rman->inotify_fd = -1; 3.43 + } 3.44 +} 3.45 + 3.46 +int resman_start_watch(struct resman *rman, struct resource *res) 3.47 +{ 3.48 + int fd; 3.49 + 3.50 + if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { 3.51 + return -1; 3.52 + } 3.53 + printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); 3.54 + rb_inserti(rman->nresmap, fd, res); 3.55 + 3.56 + res->nfd = fd; 3.57 + return 0; 3.58 +} 3.59 + 3.60 +void resman_stop_watch(struct resman *rman, struct resource *res) 3.61 +{ 3.62 + if(res->nfd > 0) { 3.63 + rb_deletei(rman->nresmap, res->nfd); 3.64 + inotify_rm_watch(rman->inotify_fd, res->nfd); 3.65 + } 3.66 +} 3.67 + 3.68 +void resman_check_watch(struct resman *rman) 3.69 +{ 3.70 + char buf[512]; 3.71 + struct inotify_event *ev; 3.72 + int sz, evsize; 3.73 + 3.74 + while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { 3.75 + ev = (struct inotify_event*)buf; 3.76 + while(sz > 0) { 3.77 + if(ev->mask & IN_MODIFY) { 3.78 + /* add the file descriptor to the modified set */ 3.79 + rb_inserti(rman->modset, ev->wd, 0); 3.80 + } 3.81 + 3.82 + evsize = sizeof *ev + ev->len; 3.83 + sz -= evsize; 3.84 + ev += evsize; 3.85 + } 3.86 + } 3.87 + 3.88 + /* for each item in the modified set, start a new job to reload it */ 3.89 + rb_foreach(rman->modset, reload_modified, rman); 3.90 + rb_clear(rman->modset); 3.91 +} 3.92 + 3.93 +/* this is called for each item in the modified set (see above) */ 3.94 +static void reload_modified(struct rbnode *node, void *cls) 3.95 +{ 3.96 + int watch_fd; 3.97 + struct resource *res; 3.98 + struct resman *rman = cls; 3.99 + 3.100 + watch_fd = rb_node_keyi(node); 3.101 + 3.102 + if(!(res = rb_findi(rman->nresmap, watch_fd))) { 3.103 + fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", 3.104 + __FUNCTION__, watch_fd); 3.105 + return; 3.106 + } 3.107 + assert(watch_fd == res->nfd); 3.108 + 3.109 + printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); 3.110 + 3.111 + tpool_add_work(rman->tpool, res); 3.112 +} 3.113 + 3.114 +#else 3.115 +int resman_filewatch_win32_silence_empty_file_warning; 3.116 +#endif /* WIN32 */
4.1 --- a/src/resman.c Wed Feb 12 22:05:28 2014 +0200 4.2 +++ b/src/resman.c Wed Feb 12 22:32:30 2014 +0200 4.3 @@ -4,58 +4,9 @@ 4.4 #include <assert.h> 4.5 #include <pthread.h> 4.6 #include "resman.h" 4.7 +#include "resman_impl.h" 4.8 #include "dynarr.h" 4.9 -#include "rbtree.h" 4.10 -#include "threadpool.h" 4.11 - 4.12 -#ifdef __linux__ 4.13 -#include <unistd.h> 4.14 -#include <fcntl.h> 4.15 -#include <sys/inotify.h> 4.16 -#endif 4.17 - 4.18 -struct resource { 4.19 - int id; 4.20 - char *name; 4.21 - void *data; 4.22 - int result; /* last callback-reported success/fail code */ 4.23 - 4.24 - int done_pending; 4.25 - int delete_pending; 4.26 - pthread_mutex_t lock; 4.27 - 4.28 - int num_loads; /* number of loads up to now */ 4.29 - 4.30 - /* file change monitoring */ 4.31 -#ifdef __WIN32__ 4.32 - HANDLE nhandle; 4.33 -#endif 4.34 -#ifdef __linux__ 4.35 - int nfd; 4.36 -#endif 4.37 -}; 4.38 - 4.39 -struct resman { 4.40 - struct resource **res; 4.41 - struct thread_pool *tpool; 4.42 - 4.43 - pthread_mutex_t lock; /* global resman lock (for res array changes) */ 4.44 - 4.45 - resman_load_func load_func; 4.46 - resman_done_func done_func; 4.47 - resman_destroy_func destroy_func; 4.48 - 4.49 - void *load_func_cls; 4.50 - void *done_func_cls; 4.51 - void *destroy_func_cls; 4.52 - 4.53 - /* file change monitoring */ 4.54 - struct rbtree *nresmap; 4.55 - struct rbtree *modset; 4.56 -#ifdef __linux__ 4.57 - int inotify_fd; 4.58 -#endif 4.59 -}; 4.60 +#include "filewatch.h" 4.61 4.62 4.63 static int find_resource(struct resman *rman, const char *fname); 4.64 @@ -63,14 +14,6 @@ 4.65 static void remove_resource(struct resman *rman, int idx); 4.66 static void work_func(void *data, void *cls); 4.67 4.68 -/* file modification watching */ 4.69 -static int init_file_monitor(struct resman *rman); 4.70 -static void destroy_file_monitor(struct resman *rman); 4.71 -static int start_watch(struct resman *rman, struct resource *res); 4.72 -static void stop_watch(struct resman *rman, struct resource *res); 4.73 -static void check_watch(struct resman *rman); 4.74 -static void reload_modified(struct rbnode *node, void *cls); 4.75 - 4.76 4.77 struct resman *resman_create(void) 4.78 { 4.79 @@ -99,7 +42,7 @@ 4.80 num_threads = atoi(env); 4.81 } 4.82 4.83 - if(init_file_monitor(rman) == -1) { 4.84 + if(resman_init_file_monitor(rman) == -1) { 4.85 return -1; 4.86 } 4.87 4.88 @@ -133,7 +76,7 @@ 4.89 4.90 tpool_free(rman->tpool); 4.91 4.92 - destroy_file_monitor(rman); 4.93 + resman_destroy_file_monitor(rman); 4.94 4.95 pthread_mutex_destroy(&rman->lock); 4.96 } 4.97 @@ -196,7 +139,7 @@ 4.98 4.99 4.100 /* then check for modified files */ 4.101 - check_watch(rman); 4.102 + resman_check_watch(rman); 4.103 4.104 4.105 if(!rman->done_func) { 4.106 @@ -230,7 +173,7 @@ 4.107 } 4.108 res->num_loads++; 4.109 4.110 - start_watch(rman, res); /* start watching the file for modifications */ 4.111 + resman_start_watch(rman, res); /* start watching the file for modifications */ 4.112 pthread_mutex_unlock(&res->lock); 4.113 } 4.114 return 0; 4.115 @@ -336,7 +279,7 @@ 4.116 /* remove a resource and leave the pointer null to reuse the slot */ 4.117 static void remove_resource(struct resman *rman, int idx) 4.118 { 4.119 - stop_watch(rman, rman->res[idx]); 4.120 + resman_stop_watch(rman, rman->res[idx]); 4.121 4.122 if(rman->destroy_func) { 4.123 rman->destroy_func(idx, rman->destroy_func_cls); 4.124 @@ -371,7 +314,7 @@ 4.125 } else { 4.126 /* succeded, start a watch */ 4.127 if(res->nfd <= 0) { 4.128 - start_watch(rman, res); 4.129 + resman_start_watch(rman, res); 4.130 } 4.131 } 4.132 } else { 4.133 @@ -380,100 +323,3 @@ 4.134 } 4.135 pthread_mutex_unlock(&res->lock); 4.136 } 4.137 - 4.138 -static int init_file_monitor(struct resman *rman) 4.139 -{ 4.140 - int fd; 4.141 - 4.142 - if((fd = inotify_init()) == -1) { 4.143 - return -1; 4.144 - } 4.145 - /* set non-blocking flag, to allow polling by reading */ 4.146 - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); 4.147 - rman->inotify_fd = fd; 4.148 - 4.149 - /* create the fd->resource map */ 4.150 - rman->nresmap = rb_create(RB_KEY_INT); 4.151 - /* create the modified set */ 4.152 - rman->modset = rb_create(RB_KEY_INT); 4.153 - return 0; 4.154 -} 4.155 - 4.156 -static void destroy_file_monitor(struct resman *rman) 4.157 -{ 4.158 - rb_free(rman->nresmap); 4.159 - rb_free(rman->modset); 4.160 - 4.161 - if(rman->inotify_fd >= 0) { 4.162 - close(rman->inotify_fd); 4.163 - rman->inotify_fd = -1; 4.164 - } 4.165 -} 4.166 - 4.167 -static int start_watch(struct resman *rman, struct resource *res) 4.168 -{ 4.169 - int fd; 4.170 - 4.171 - if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { 4.172 - return -1; 4.173 - } 4.174 - printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); 4.175 - rb_inserti(rman->nresmap, fd, res); 4.176 - 4.177 - res->nfd = fd; 4.178 - return 0; 4.179 -} 4.180 - 4.181 -static void stop_watch(struct resman *rman, struct resource *res) 4.182 -{ 4.183 - if(res->nfd > 0) { 4.184 - rb_deletei(rman->nresmap, res->nfd); 4.185 - inotify_rm_watch(rman->inotify_fd, res->nfd); 4.186 - } 4.187 -} 4.188 - 4.189 -static void check_watch(struct resman *rman) 4.190 -{ 4.191 - char buf[512]; 4.192 - struct inotify_event *ev; 4.193 - int sz, evsize; 4.194 - 4.195 - while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { 4.196 - ev = (struct inotify_event*)buf; 4.197 - while(sz > 0) { 4.198 - if(ev->mask & IN_MODIFY) { 4.199 - /* add the file descriptor to the modified set */ 4.200 - rb_inserti(rman->modset, ev->wd, 0); 4.201 - } 4.202 - 4.203 - evsize = sizeof *ev + ev->len; 4.204 - sz -= evsize; 4.205 - ev += evsize; 4.206 - } 4.207 - } 4.208 - 4.209 - /* for each item in the modified set, start a new job to reload it */ 4.210 - rb_foreach(rman->modset, reload_modified, rman); 4.211 - rb_clear(rman->modset); 4.212 -} 4.213 - 4.214 -/* this is called for each item in the modified set (see above) */ 4.215 -static void reload_modified(struct rbnode *node, void *cls) 4.216 -{ 4.217 - int watch_fd; 4.218 - struct resource *res; 4.219 - struct resman *rman = cls; 4.220 - 4.221 - watch_fd = rb_node_keyi(node); 4.222 - 4.223 - if(!(res = rb_findi(rman->nresmap, watch_fd))) { 4.224 - fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", 4.225 - __FUNCTION__, watch_fd); 4.226 - return; 4.227 - } 4.228 - assert(watch_fd == res->nfd); 4.229 - 4.230 - printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); 4.231 - 4.232 - tpool_add_work(rman->tpool, res); 4.233 -}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/resman_impl.h Wed Feb 12 22:32:30 2014 +0200 5.3 @@ -0,0 +1,59 @@ 5.4 +#ifndef RESMAN_IMPL_H_ 5.5 +#define RESMAN_IMPL_H_ 5.6 + 5.7 +#include <pthread.h> 5.8 +#include "rbtree.h" 5.9 +#include "threadpool.h" 5.10 + 5.11 +#ifdef __linux__ 5.12 +#include <unistd.h> 5.13 +#include <fcntl.h> 5.14 +#include <sys/inotify.h> 5.15 +#endif 5.16 + 5.17 +struct resource { 5.18 + int id; 5.19 + char *name; 5.20 + void *data; 5.21 + int result; /* last callback-reported success/fail code */ 5.22 + 5.23 + int done_pending; 5.24 + int delete_pending; 5.25 + pthread_mutex_t lock; 5.26 + 5.27 + int num_loads; /* number of loads up to now */ 5.28 + 5.29 + /* file change monitoring */ 5.30 +#ifdef __WIN32__ 5.31 + HANDLE nhandle; 5.32 +#endif 5.33 +#ifdef __linux__ 5.34 + int nfd; 5.35 +#endif 5.36 +}; 5.37 + 5.38 + 5.39 +struct resman { 5.40 + struct resource **res; 5.41 + struct thread_pool *tpool; 5.42 + 5.43 + pthread_mutex_t lock; /* global resman lock (for res array changes) */ 5.44 + 5.45 + resman_load_func load_func; 5.46 + resman_done_func done_func; 5.47 + resman_destroy_func destroy_func; 5.48 + 5.49 + void *load_func_cls; 5.50 + void *done_func_cls; 5.51 + void *destroy_func_cls; 5.52 + 5.53 + /* file change monitoring */ 5.54 + struct rbtree *nresmap; 5.55 + struct rbtree *modset; 5.56 +#ifdef __linux__ 5.57 + int inotify_fd; 5.58 +#endif 5.59 +}; 5.60 + 5.61 + 5.62 +#endif /* RESMAN_IMPL_H_ */