# HG changeset patch # User John Tsiombikas # Date 1392237150 -7200 # Node ID 174ddb6bf92adc5547d6fb9fe0d51daf4e6d4e88 # Parent fe0dbdfbe403b0f2bdd6ec9d6dafe55d6880eb20 separated platform-specific filewatch code diff -r fe0dbdfbe403 -r 174ddb6bf92a src/filewatch.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filewatch.h Wed Feb 12 22:32:30 2014 +0200 @@ -0,0 +1,15 @@ +#ifndef FILEWATCH_H_ +#define FILEWATCH_H_ + +struct resman; +struct resource; + +int resman_init_file_monitor(struct resman *rman); +void resman_destroy_file_monitor(struct resman *rman); + +int resman_start_watch(struct resman *rman, struct resource *res); +void resman_stop_watch(struct resman *rman, struct resource *res); + +void resman_check_watch(struct resman *rman); + +#endif /* FILEWATCH_H_ */ diff -r fe0dbdfbe403 -r 174ddb6bf92a src/filewatch_linux.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filewatch_linux.c Wed Feb 12 22:32:30 2014 +0200 @@ -0,0 +1,113 @@ +/* file modification monitoring with inotify */ +#ifdef __linux__ +#include +#include +#include +#include +#include +#include "filewatch.h" +#include "resman.h" +#include "resman_impl.h" + +static void reload_modified(struct rbnode *node, void *cls); + +int resman_init_file_monitor(struct resman *rman) +{ + int fd; + + if((fd = inotify_init()) == -1) { + return -1; + } + /* set non-blocking flag, to allow polling by reading */ + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + rman->inotify_fd = fd; + + /* create the fd->resource map */ + rman->nresmap = rb_create(RB_KEY_INT); + /* create the modified set */ + rman->modset = rb_create(RB_KEY_INT); + return 0; +} + +void resman_destroy_file_monitor(struct resman *rman) +{ + rb_free(rman->nresmap); + rb_free(rman->modset); + + if(rman->inotify_fd >= 0) { + close(rman->inotify_fd); + rman->inotify_fd = -1; + } +} + +int resman_start_watch(struct resman *rman, struct resource *res) +{ + int fd; + + if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { + return -1; + } + printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); + rb_inserti(rman->nresmap, fd, res); + + res->nfd = fd; + return 0; +} + +void resman_stop_watch(struct resman *rman, struct resource *res) +{ + if(res->nfd > 0) { + rb_deletei(rman->nresmap, res->nfd); + inotify_rm_watch(rman->inotify_fd, res->nfd); + } +} + +void resman_check_watch(struct resman *rman) +{ + char buf[512]; + struct inotify_event *ev; + int sz, evsize; + + while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { + ev = (struct inotify_event*)buf; + while(sz > 0) { + if(ev->mask & IN_MODIFY) { + /* add the file descriptor to the modified set */ + rb_inserti(rman->modset, ev->wd, 0); + } + + evsize = sizeof *ev + ev->len; + sz -= evsize; + ev += evsize; + } + } + + /* for each item in the modified set, start a new job to reload it */ + rb_foreach(rman->modset, reload_modified, rman); + rb_clear(rman->modset); +} + +/* this is called for each item in the modified set (see above) */ +static void reload_modified(struct rbnode *node, void *cls) +{ + int watch_fd; + struct resource *res; + struct resman *rman = cls; + + watch_fd = rb_node_keyi(node); + + if(!(res = rb_findi(rman->nresmap, watch_fd))) { + fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", + __FUNCTION__, watch_fd); + return; + } + assert(watch_fd == res->nfd); + + printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); + + tpool_add_work(rman->tpool, res); +} + +#else +int resman_filewatch_linux_silence_empty_file_warning; +#endif /* __linux__ */ diff -r fe0dbdfbe403 -r 174ddb6bf92a src/filewatch_win32.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/filewatch_win32.c Wed Feb 12 22:32:30 2014 +0200 @@ -0,0 +1,113 @@ +/* file modification monitoring for windows */ +#ifdef WIN32 +#include +#include +#include +#include +#include +#include "filewatch.h" +#include "resman.h" +#include "resman_impl.h" + +static void reload_modified(struct rbnode *node, void *cls); + +int resman_init_file_monitor(struct resman *rman) +{ + int fd; + + if((fd = inotify_init()) == -1) { + return -1; + } + /* set non-blocking flag, to allow polling by reading */ + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); + rman->inotify_fd = fd; + + /* create the fd->resource map */ + rman->nresmap = rb_create(RB_KEY_INT); + /* create the modified set */ + rman->modset = rb_create(RB_KEY_INT); + return 0; +} + +void resman_destroy_file_monitor(struct resman *rman) +{ + rb_free(rman->nresmap); + rb_free(rman->modset); + + if(rman->inotify_fd >= 0) { + close(rman->inotify_fd); + rman->inotify_fd = -1; + } +} + +int resman_start_watch(struct resman *rman, struct resource *res) +{ + int fd; + + if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { + return -1; + } + printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); + rb_inserti(rman->nresmap, fd, res); + + res->nfd = fd; + return 0; +} + +void resman_stop_watch(struct resman *rman, struct resource *res) +{ + if(res->nfd > 0) { + rb_deletei(rman->nresmap, res->nfd); + inotify_rm_watch(rman->inotify_fd, res->nfd); + } +} + +void resman_check_watch(struct resman *rman) +{ + char buf[512]; + struct inotify_event *ev; + int sz, evsize; + + while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { + ev = (struct inotify_event*)buf; + while(sz > 0) { + if(ev->mask & IN_MODIFY) { + /* add the file descriptor to the modified set */ + rb_inserti(rman->modset, ev->wd, 0); + } + + evsize = sizeof *ev + ev->len; + sz -= evsize; + ev += evsize; + } + } + + /* for each item in the modified set, start a new job to reload it */ + rb_foreach(rman->modset, reload_modified, rman); + rb_clear(rman->modset); +} + +/* this is called for each item in the modified set (see above) */ +static void reload_modified(struct rbnode *node, void *cls) +{ + int watch_fd; + struct resource *res; + struct resman *rman = cls; + + watch_fd = rb_node_keyi(node); + + if(!(res = rb_findi(rman->nresmap, watch_fd))) { + fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", + __FUNCTION__, watch_fd); + return; + } + assert(watch_fd == res->nfd); + + printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); + + tpool_add_work(rman->tpool, res); +} + +#else +int resman_filewatch_win32_silence_empty_file_warning; +#endif /* WIN32 */ diff -r fe0dbdfbe403 -r 174ddb6bf92a src/resman.c --- a/src/resman.c Wed Feb 12 22:05:28 2014 +0200 +++ b/src/resman.c Wed Feb 12 22:32:30 2014 +0200 @@ -4,58 +4,9 @@ #include #include #include "resman.h" +#include "resman_impl.h" #include "dynarr.h" -#include "rbtree.h" -#include "threadpool.h" - -#ifdef __linux__ -#include -#include -#include -#endif - -struct resource { - int id; - char *name; - void *data; - int result; /* last callback-reported success/fail code */ - - int done_pending; - int delete_pending; - pthread_mutex_t lock; - - int num_loads; /* number of loads up to now */ - - /* file change monitoring */ -#ifdef __WIN32__ - HANDLE nhandle; -#endif -#ifdef __linux__ - int nfd; -#endif -}; - -struct resman { - struct resource **res; - struct thread_pool *tpool; - - pthread_mutex_t lock; /* global resman lock (for res array changes) */ - - resman_load_func load_func; - resman_done_func done_func; - resman_destroy_func destroy_func; - - void *load_func_cls; - void *done_func_cls; - void *destroy_func_cls; - - /* file change monitoring */ - struct rbtree *nresmap; - struct rbtree *modset; -#ifdef __linux__ - int inotify_fd; -#endif -}; +#include "filewatch.h" static int find_resource(struct resman *rman, const char *fname); @@ -63,14 +14,6 @@ static void remove_resource(struct resman *rman, int idx); static void work_func(void *data, void *cls); -/* file modification watching */ -static int init_file_monitor(struct resman *rman); -static void destroy_file_monitor(struct resman *rman); -static int start_watch(struct resman *rman, struct resource *res); -static void stop_watch(struct resman *rman, struct resource *res); -static void check_watch(struct resman *rman); -static void reload_modified(struct rbnode *node, void *cls); - struct resman *resman_create(void) { @@ -99,7 +42,7 @@ num_threads = atoi(env); } - if(init_file_monitor(rman) == -1) { + if(resman_init_file_monitor(rman) == -1) { return -1; } @@ -133,7 +76,7 @@ tpool_free(rman->tpool); - destroy_file_monitor(rman); + resman_destroy_file_monitor(rman); pthread_mutex_destroy(&rman->lock); } @@ -196,7 +139,7 @@ /* then check for modified files */ - check_watch(rman); + resman_check_watch(rman); if(!rman->done_func) { @@ -230,7 +173,7 @@ } res->num_loads++; - start_watch(rman, res); /* start watching the file for modifications */ + resman_start_watch(rman, res); /* start watching the file for modifications */ pthread_mutex_unlock(&res->lock); } return 0; @@ -336,7 +279,7 @@ /* remove a resource and leave the pointer null to reuse the slot */ static void remove_resource(struct resman *rman, int idx) { - stop_watch(rman, rman->res[idx]); + resman_stop_watch(rman, rman->res[idx]); if(rman->destroy_func) { rman->destroy_func(idx, rman->destroy_func_cls); @@ -371,7 +314,7 @@ } else { /* succeded, start a watch */ if(res->nfd <= 0) { - start_watch(rman, res); + resman_start_watch(rman, res); } } } else { @@ -380,100 +323,3 @@ } pthread_mutex_unlock(&res->lock); } - -static int init_file_monitor(struct resman *rman) -{ - int fd; - - if((fd = inotify_init()) == -1) { - return -1; - } - /* set non-blocking flag, to allow polling by reading */ - fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); - rman->inotify_fd = fd; - - /* create the fd->resource map */ - rman->nresmap = rb_create(RB_KEY_INT); - /* create the modified set */ - rman->modset = rb_create(RB_KEY_INT); - return 0; -} - -static void destroy_file_monitor(struct resman *rman) -{ - rb_free(rman->nresmap); - rb_free(rman->modset); - - if(rman->inotify_fd >= 0) { - close(rman->inotify_fd); - rman->inotify_fd = -1; - } -} - -static int start_watch(struct resman *rman, struct resource *res) -{ - int fd; - - if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) { - return -1; - } - printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd); - rb_inserti(rman->nresmap, fd, res); - - res->nfd = fd; - return 0; -} - -static void stop_watch(struct resman *rman, struct resource *res) -{ - if(res->nfd > 0) { - rb_deletei(rman->nresmap, res->nfd); - inotify_rm_watch(rman->inotify_fd, res->nfd); - } -} - -static void check_watch(struct resman *rman) -{ - char buf[512]; - struct inotify_event *ev; - int sz, evsize; - - while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) { - ev = (struct inotify_event*)buf; - while(sz > 0) { - if(ev->mask & IN_MODIFY) { - /* add the file descriptor to the modified set */ - rb_inserti(rman->modset, ev->wd, 0); - } - - evsize = sizeof *ev + ev->len; - sz -= evsize; - ev += evsize; - } - } - - /* for each item in the modified set, start a new job to reload it */ - rb_foreach(rman->modset, reload_modified, rman); - rb_clear(rman->modset); -} - -/* this is called for each item in the modified set (see above) */ -static void reload_modified(struct rbnode *node, void *cls) -{ - int watch_fd; - struct resource *res; - struct resman *rman = cls; - - watch_fd = rb_node_keyi(node); - - if(!(res = rb_findi(rman->nresmap, watch_fd))) { - fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n", - __FUNCTION__, watch_fd); - return; - } - assert(watch_fd == res->nfd); - - printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node)); - - tpool_add_work(rman->tpool, res); -} diff -r fe0dbdfbe403 -r 174ddb6bf92a src/resman_impl.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/resman_impl.h Wed Feb 12 22:32:30 2014 +0200 @@ -0,0 +1,59 @@ +#ifndef RESMAN_IMPL_H_ +#define RESMAN_IMPL_H_ + +#include +#include "rbtree.h" +#include "threadpool.h" + +#ifdef __linux__ +#include +#include +#include +#endif + +struct resource { + int id; + char *name; + void *data; + int result; /* last callback-reported success/fail code */ + + int done_pending; + int delete_pending; + pthread_mutex_t lock; + + int num_loads; /* number of loads up to now */ + + /* file change monitoring */ +#ifdef __WIN32__ + HANDLE nhandle; +#endif +#ifdef __linux__ + int nfd; +#endif +}; + + +struct resman { + struct resource **res; + struct thread_pool *tpool; + + pthread_mutex_t lock; /* global resman lock (for res array changes) */ + + resman_load_func load_func; + resman_done_func done_func; + resman_destroy_func destroy_func; + + void *load_func_cls; + void *done_func_cls; + void *destroy_func_cls; + + /* file change monitoring */ + struct rbtree *nresmap; + struct rbtree *modset; +#ifdef __linux__ + int inotify_fd; +#endif +}; + + +#endif /* RESMAN_IMPL_H_ */