libresman

diff src/resman.c @ 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
line diff
     1.1 --- a/src/resman.c	Wed Feb 12 22:05:28 2014 +0200
     1.2 +++ b/src/resman.c	Wed Feb 12 22:32:30 2014 +0200
     1.3 @@ -4,58 +4,9 @@
     1.4  #include <assert.h>
     1.5  #include <pthread.h>
     1.6  #include "resman.h"
     1.7 +#include "resman_impl.h"
     1.8  #include "dynarr.h"
     1.9 -#include "rbtree.h"
    1.10 -#include "threadpool.h"
    1.11 -
    1.12 -#ifdef __linux__
    1.13 -#include <unistd.h>
    1.14 -#include <fcntl.h>
    1.15 -#include <sys/inotify.h>
    1.16 -#endif
    1.17 -
    1.18 -struct resource {
    1.19 -	int id;
    1.20 -	char *name;
    1.21 -	void *data;
    1.22 -	int result;	/* last callback-reported success/fail code */
    1.23 -
    1.24 -	int done_pending;
    1.25 -	int delete_pending;
    1.26 -	pthread_mutex_t lock;
    1.27 -
    1.28 -	int num_loads;		/* number of loads up to now */
    1.29 -
    1.30 -	/* file change monitoring */
    1.31 -#ifdef __WIN32__
    1.32 -	HANDLE nhandle;
    1.33 -#endif
    1.34 -#ifdef __linux__
    1.35 -	int nfd;
    1.36 -#endif
    1.37 -};
    1.38 -
    1.39 -struct resman {
    1.40 -	struct resource **res;
    1.41 -	struct thread_pool *tpool;
    1.42 -
    1.43 -	pthread_mutex_t lock;	/* global resman lock (for res array changes) */
    1.44 -
    1.45 -	resman_load_func load_func;
    1.46 -	resman_done_func done_func;
    1.47 -	resman_destroy_func destroy_func;
    1.48 -
    1.49 -	void *load_func_cls;
    1.50 -	void *done_func_cls;
    1.51 -	void *destroy_func_cls;
    1.52 -
    1.53 -	/* file change monitoring */
    1.54 -	struct rbtree *nresmap;
    1.55 -	struct rbtree *modset;
    1.56 -#ifdef __linux__
    1.57 -	int inotify_fd;
    1.58 -#endif
    1.59 -};
    1.60 +#include "filewatch.h"
    1.61  
    1.62  
    1.63  static int find_resource(struct resman *rman, const char *fname);
    1.64 @@ -63,14 +14,6 @@
    1.65  static void remove_resource(struct resman *rman, int idx);
    1.66  static void work_func(void *data, void *cls);
    1.67  
    1.68 -/* file modification watching */
    1.69 -static int init_file_monitor(struct resman *rman);
    1.70 -static void destroy_file_monitor(struct resman *rman);
    1.71 -static int start_watch(struct resman *rman, struct resource *res);
    1.72 -static void stop_watch(struct resman *rman, struct resource *res);
    1.73 -static void check_watch(struct resman *rman);
    1.74 -static void reload_modified(struct rbnode *node, void *cls);
    1.75 -
    1.76  
    1.77  struct resman *resman_create(void)
    1.78  {
    1.79 @@ -99,7 +42,7 @@
    1.80  		num_threads = atoi(env);
    1.81  	}
    1.82  
    1.83 -	if(init_file_monitor(rman) == -1) {
    1.84 +	if(resman_init_file_monitor(rman) == -1) {
    1.85  		return -1;
    1.86  	}
    1.87  
    1.88 @@ -133,7 +76,7 @@
    1.89  
    1.90  	tpool_free(rman->tpool);
    1.91  
    1.92 -	destroy_file_monitor(rman);
    1.93 +	resman_destroy_file_monitor(rman);
    1.94  
    1.95  	pthread_mutex_destroy(&rman->lock);
    1.96  }
    1.97 @@ -196,7 +139,7 @@
    1.98  
    1.99  
   1.100  	/* then check for modified files */
   1.101 -	check_watch(rman);
   1.102 +	resman_check_watch(rman);
   1.103  
   1.104  
   1.105  	if(!rman->done_func) {
   1.106 @@ -230,7 +173,7 @@
   1.107  		}
   1.108  		res->num_loads++;
   1.109  
   1.110 -		start_watch(rman, res);	/* start watching the file for modifications */
   1.111 +		resman_start_watch(rman, res);	/* start watching the file for modifications */
   1.112  		pthread_mutex_unlock(&res->lock);
   1.113  	}
   1.114  	return 0;
   1.115 @@ -336,7 +279,7 @@
   1.116  /* remove a resource and leave the pointer null to reuse the slot */
   1.117  static void remove_resource(struct resman *rman, int idx)
   1.118  {
   1.119 -	stop_watch(rman, rman->res[idx]);
   1.120 +	resman_stop_watch(rman, rman->res[idx]);
   1.121  
   1.122  	if(rman->destroy_func) {
   1.123  		rman->destroy_func(idx, rman->destroy_func_cls);
   1.124 @@ -371,7 +314,7 @@
   1.125  		} else {
   1.126  			/* succeded, start a watch */
   1.127  			if(res->nfd <= 0) {
   1.128 -				start_watch(rman, res);
   1.129 +				resman_start_watch(rman, res);
   1.130  			}
   1.131  		}
   1.132  	} else {
   1.133 @@ -380,100 +323,3 @@
   1.134  	}
   1.135  	pthread_mutex_unlock(&res->lock);
   1.136  }
   1.137 -
   1.138 -static int init_file_monitor(struct resman *rman)
   1.139 -{
   1.140 -	int fd;
   1.141 -
   1.142 -	if((fd = inotify_init()) == -1) {
   1.143 -		return -1;
   1.144 -	}
   1.145 -	/* set non-blocking flag, to allow polling by reading */
   1.146 -	fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
   1.147 -	rman->inotify_fd = fd;
   1.148 -
   1.149 -	/* create the fd->resource map */
   1.150 -	rman->nresmap = rb_create(RB_KEY_INT);
   1.151 -	/* create the modified set */
   1.152 -	rman->modset = rb_create(RB_KEY_INT);
   1.153 -	return 0;
   1.154 -}
   1.155 -
   1.156 -static void destroy_file_monitor(struct resman *rman)
   1.157 -{
   1.158 -	rb_free(rman->nresmap);
   1.159 -	rb_free(rman->modset);
   1.160 -
   1.161 -	if(rman->inotify_fd >= 0) {
   1.162 -		close(rman->inotify_fd);
   1.163 -		rman->inotify_fd = -1;
   1.164 -	}
   1.165 -}
   1.166 -
   1.167 -static int start_watch(struct resman *rman, struct resource *res)
   1.168 -{
   1.169 -	int fd;
   1.170 -
   1.171 -	if((fd = inotify_add_watch(rman->inotify_fd, res->name, IN_MODIFY)) == -1) {
   1.172 -		return -1;
   1.173 -	}
   1.174 -	printf("started watching file \"%s\" for modification (fd %d)\n", res->name, fd);
   1.175 -	rb_inserti(rman->nresmap, fd, res);
   1.176 -
   1.177 -	res->nfd = fd;
   1.178 -	return 0;
   1.179 -}
   1.180 -
   1.181 -static void stop_watch(struct resman *rman, struct resource *res)
   1.182 -{
   1.183 -	if(res->nfd > 0) {
   1.184 -		rb_deletei(rman->nresmap, res->nfd);
   1.185 -		inotify_rm_watch(rman->inotify_fd, res->nfd);
   1.186 -	}
   1.187 -}
   1.188 -
   1.189 -static void check_watch(struct resman *rman)
   1.190 -{
   1.191 -	char buf[512];
   1.192 -	struct inotify_event *ev;
   1.193 -	int sz, evsize;
   1.194 -
   1.195 -	while((sz = read(rman->inotify_fd, buf, sizeof buf)) > 0) {
   1.196 -		ev = (struct inotify_event*)buf;
   1.197 -		while(sz > 0) {
   1.198 -			if(ev->mask & IN_MODIFY) {
   1.199 -				/* add the file descriptor to the modified set */
   1.200 -				rb_inserti(rman->modset, ev->wd, 0);
   1.201 -			}
   1.202 -
   1.203 -			evsize = sizeof *ev + ev->len;
   1.204 -			sz -= evsize;
   1.205 -			ev += evsize;
   1.206 -		}
   1.207 -	}
   1.208 -
   1.209 -	/* for each item in the modified set, start a new job to reload it */
   1.210 -	rb_foreach(rman->modset, reload_modified, rman);
   1.211 -	rb_clear(rman->modset);
   1.212 -}
   1.213 -
   1.214 -/* this is called for each item in the modified set (see above) */
   1.215 -static void reload_modified(struct rbnode *node, void *cls)
   1.216 -{
   1.217 -	int watch_fd;
   1.218 -	struct resource *res;
   1.219 -	struct resman *rman = cls;
   1.220 -
   1.221 -	watch_fd = rb_node_keyi(node);
   1.222 -
   1.223 -	if(!(res = rb_findi(rman->nresmap, watch_fd))) {
   1.224 -		fprintf(stderr, "%s: can't find resource for watch descriptor: %d\n",
   1.225 -				__FUNCTION__, watch_fd);
   1.226 -		return;
   1.227 -	}
   1.228 -	assert(watch_fd == res->nfd);
   1.229 -
   1.230 -	printf("file \"%s\" modified (fd %d)\n", res->name, rb_node_keyi(node));
   1.231 -
   1.232 -	tpool_add_work(rman->tpool, res);
   1.233 -}