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