↑ 1 #ifndef RH_STAT_H
↑ 2 #define RH_STAT_H
↑ 3
↑ 4 #include <sys/types.h>
↑ 5 #include <sys/stat.h>
↑ 6 #include "rh_gmtime.h"
↑ 7 #include "rh_event.h"
↑ 8 #include "rh_buffer.h"
↑ 9 #include "queue.h"
↑ 10 #include "mimetype.h"
↑ 11
↑ 12 /**
↑ 13 *
↑ 14 * @file rh_stat.h
↑ 15 * @author Ralf Huesing <ralf@stormbind.net>
↑ 16 *
↑ 17 *
↑ 18 * Description
↑ 19 * ^^^^^^^^^^^
↑ 20 *
↑ 21 * rh_stat is a stat cache using inotify notification introduced
↑ 22 * in linux 2.6.??.
↑ 23 *
↑ 24 * using a stat cache that is not up to date is a problem since
↑ 25 * this may give wrong information about file. for example
↑ 26 * the file may be changed (size, times, ..) or removed.
↑ 27 *
↑ 28 * rh_stat trys to solve this problem with inotify().
↑ 29 *
↑ 30 * inotify() only cover existent files.
↑ 31 *
↑ 32 * therefore there is a time leak for non existent files, a short example:
↑ 33 *
↑ 34 * stat(not_exist) -> cached for a few seconds (5 or so)
↑ 35 * ...
↑ 36 * create the file
↑ 37 * ...
↑ 38 * stat(not_exist) -> file exists but the cache still says "no"
↑ 39 *
↑ 40 * there are some macros that defines timeouts (in seconds):
↑ 41 *
↑ 42 * RHTTPD_STAT_CACHE_FREE_INTERVAL
↑ 43 *
↑ 44 * it makes no sense to have a stat cache that knows
↑ 45 * all the files you have.
↑ 46 * this timeout says when to remove cached but unused entries
↑ 47 * since .. seconds. this maybe a "large", lets say 1 minute.
↑ 48 *
↑ 49 * RHTTPD_STAT_CACHE_TIMEOUT
↑ 50 *
↑ 51 * as explained above not all files are inofity'd.
↑ 52 *
↑ 53 * this timeout defines when to re-stat() not inotify'd files.
↑ 54 * this value should be short, lets say 5 seconds.
↑ 55 *
↑ 56 *
↑ 57 * RHTTPD_STAT_CLEANUP_INTERVAL
↑ 58 *
↑ 59 * this is defines when to call the cleanup routine which
↑ 60 * finds timeouted entries defined by RHTTPD_STAT_CACHE_FREE_INTERVAL.
↑ 61 *
↑ 62 *
↑ 63 * timeouts only tested if you rh_stat() something.
↑ 64 *
↑ 65 * for example if you stat "now" all your files and then no more
↑ 66 * you will fill your memory with unused data which will never free'd.
↑ 67 *
↑ 68 * rh_stat was build to use with a httpd, as a result of this rh_stat
↑ 69 * knows:
↑ 70 * the mime type of a file
↑ 71 * the last modification time as a http conform GMT string
↑ 72 *
↑ 73 * since this is a cache the above values also cached.
↑ 74 *
↑ 75 *
↑ 76 */
↑ 77
↑ 78 typedef struct rh_stat rh_stat_t;
↑ 79 typedef struct rh_stat_cache rh_stat_cache_t;
↑ 80
↑ 81 TAILQ_HEAD(rh_stat_cache_list, rh_stat);
↑ 82
↑ 83 struct rh_stat_cache {
↑ 84 rh_event_base_t *ev_base;
↑ 85
↑ 86 struct rh_stat_inotify *inotify; /* current inotify
↑ 87 structure */
↑ 88
↑ 89 struct rh_stat_cache_list timeout; /* list holding
↑ 90 unused entries
↑ 91 which may timeout */
↑ 92
↑ 93 struct rh_stat_cache_list *buckets; /* rh_stat_t hash */
↑ 94 size_t nbuckets;
↑ 95 size_t elements;
↑ 96
↑ 97 time_t last_cleanup; /* time of last cleanup
↑ 98 run */
↑ 99
↑100 mimetype_base_t *mimebase;
↑101
↑102 FIXED_BUFFER(,4092) buffer; /* buffer for
↑103 read(fd_inotify) */
↑104 };
↑105
↑106 struct rh_stat {
↑107 struct rh_stat_cache *cache; /* backward pointer to the
↑108 cache */
↑109
↑110 struct rh_stat_inotify *inotify; /* with which inotify
↑111 struct this is
↑112 inotify'd */
↑113
↑114 int removed;
↑115
↑116 rh_buffer_t path; /* stat()'ed filename */
↑117
↑118 struct stat stbuf; /* the stat() buffer */
↑119
↑120 int error; /* errno if stat() failed */
↑121
↑122 int wd; /* watch descriptor */
↑123
↑124 size_t used; /* used counter */
↑125
↑126 time_t atime; /* last access time
↑127 of this structure */
↑128
↑129 time_t mtime; /* last modification time
↑130 of this structure
↑131 (stat() was called) */
↑132
↑133 rh_gmtime_t gmtime; /* GMT string */
↑134
↑135 mimetype_t mime; /* mime type */
↑136
↑137 TAILQ_ENTRY(rh_stat) timeout;
↑138 TAILQ_ENTRY(rh_stat) hash;
↑139 };
↑140
↑141 int rh_stat_cache_init (rh_stat_cache_t *cache, rh_event_base_t *ev_base,
↑142 mimetype_base_t *mimebase);
↑143
↑144 void rh_stat_cache_destroy (rh_stat_cache_t *);
↑145
↑146 rh_stat_t * rh_stat_pop (rh_stat_cache_t *, rh_buffer_t *filename);
↑147
↑148
↑149 /* always call push() on a pop()'d rh_stat() if you dont need it anymore.
↑150 *
↑151 * remember that the buffers (gmtime, mimetime, path) maybe invalid
↑152 * because this may free()'s it */
↑153 void rh_stat_push (rh_stat_t *stbuf);
↑154
↑155 #define RH_STAT_ISERROR(_st) ( 0 != ((_st)->error) )
↑156 #define RH_STAT_ISDIR(_st) ( S_ISDIR((_st)->stbuf.st_mode) )
↑157 #define RH_STAT_ISREG(_st) ( S_ISREG((_st)->stbuf.st_mode) )
↑158
↑159 #endif /* RH_STAT_H */
syntax highlighted by Code2HTML, v. 0.9.1