Loading modules/cache/mod_file_cache.c +72 −125 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ #include "apr.h" #include "apr_mmap.h" #include "apr_strings.h" #include "apr_hash.h" #define APR_WANT_STRFUNC #include "apr_want.h" Loading Loading @@ -143,7 +144,7 @@ typedef struct { } a_file; typedef struct { apr_array_header_t *files; apr_hash_t *fileht; } a_server_config; Loading @@ -151,176 +152,124 @@ static void *create_server_config(apr_pool_t *p, server_rec *s) { a_server_config *sconf = apr_palloc(p, sizeof(*sconf)); sconf->files = apr_array_make(p, 20, sizeof(a_file)); sconf->fileht = apr_hash_make(p); return sconf; } static apr_status_t cleanup_file_cache(void *sconfv) { a_server_config *sconf = sconfv; size_t n; a_file *file; apr_hash_index_t *hi; n = sconf->files->nelts; file = (a_file *)sconf->files->elts; while(n) { /* Iterate over the file hash table and clean up each entry */ for (hi = apr_hash_first(sconf->fileht); hi; hi=apr_hash_next(hi)) { apr_hash_this(hi, NULL, NULL, &file); #if APR_HAS_MMAP if (file->is_mmapped) { apr_mmap_delete(file->mm); } else #endif #if APR_HAS_SENDFILE if (!file->is_mmapped) { apr_file_close(file->file); } #endif ++file; --n; } return APR_SUCCESS; } static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename) static void cache_the_file(cmd_parms *cmd, const char *filename, int mmap) { /* ToDo: * Disable the file cache on a Windows 9X box. APR_HAS_SENDFILE will be * defined in an Apache for Windows build, but apr_sendfile returns * APR_ENOTIMPL on Windows 9X because TransmitFile is not available. */ #if APR_HAS_SENDFILE a_server_config *sconf; a_file *new_file; a_file tmp; apr_file_t *fd = NULL; apr_status_t rc; const char *fspec; /* canonicalize the file name? */ /* os_canonical... */ /* XXX: uh... yea, or expect them to be -very- accurate typists */ if ((rc = apr_stat(&tmp.finfo, filename, APR_FINFO_MIN, fspec = ap_os_case_canonical_filename(cmd->pool, filename); if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to stat(%s), skipping", filename); return NULL; "mod_file_cache: unable to stat(%s), skipping", fspec); return; } if (tmp.finfo.filetype != APR_REG) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: %s isn't a regular file, skipping", filename); return NULL; "mod_file_cache: %s isn't a regular file, skipping", fspec); return; } rc = apr_file_open(&fd, filename, APR_READ | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool); rc = apr_file_open(&fd, fspec, APR_READ | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to open(%s, O_RDONLY), skipping", filename); return NULL; } tmp.file = fd; tmp.filename = apr_pstrdup(cmd->pool, filename); apr_rfc822_date(tmp.mtimestr, tmp.finfo.mtime); apr_snprintf(tmp.sizestr, sizeof tmp.sizestr, "%" APR_OFF_T_FMT, tmp.finfo.size); sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module); new_file = apr_array_push(sconf->files); *new_file = tmp; if (sconf->files->nelts == 1) { /* first one, register the cleanup */ apr_pool_cleanup_register(cmd->pool, sconf, cleanup_file_cache, apr_pool_cleanup_null); "mod_file_cache: unable to open(%s, O_RDONLY), skipping", fspec); return; } new_file->is_mmapped = FALSE; /* WooHoo, we have a file to put in the cache */ new_file = apr_pcalloc(cmd->pool, sizeof(a_file)); new_file->finfo = tmp.finfo; return NULL; #else /* Sendfile not supported on this platform */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", filename); return NULL; #endif } static const char *mmapfile(cmd_parms *cmd, void *dummy, const char *filename) { #if APR_HAS_MMAP a_server_config *sconf; a_file *new_file; a_file tmp; apr_file_t *fd = NULL; apr_status_t rc; const char *fspec; fspec = ap_os_case_canonical_filename(cmd->pool, filename); if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to stat(%s), skipping", filename); return NULL; } if ((tmp.finfo.filetype) != APR_REG) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: %s isn't a regular file, skipping", filename); return NULL; } if ((rc = apr_file_open(&fd, fspec, APR_READ, APR_OS_DEFAULT, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to open %s, skipping", filename); return NULL; } if ((rc = apr_mmap_create(&tmp.mm, fd, 0, tmp.finfo.size, APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) { if (mmap) { /* MMAPFile directive. MMAP'ing the file */ if ((rc = apr_mmap_create(&new_file->mm, fd, 0, new_file->finfo.size, APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) { apr_file_close(fd); ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to mmap %s, skipping", filename); return NULL; return; } apr_file_close(fd); tmp.filename = fspec; apr_rfc822_date(tmp.mtimestr, tmp.finfo.mtime); apr_snprintf(tmp.sizestr, sizeof tmp.sizestr, "%" APR_OFF_T_FMT, tmp.finfo.size); new_file->is_mmapped = TRUE; } else { /* CacheFile directive. Caching the file handle */ new_file->is_mmapped = FALSE; new_file->file = fd; } new_file->filename = fspec; apr_rfc822_date(new_file->mtimestr, new_file->finfo.mtime); apr_snprintf(new_file->sizestr, sizeof new_file->sizestr, "%" APR_OFF_T_FMT, new_file->finfo.size); sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module); new_file = apr_array_push(sconf->files); *new_file = tmp; if (sconf->files->nelts == 1) { apr_hash_set(sconf->fileht, new_file->filename, strlen(new_file->filename), new_file); if (apr_hash_count(sconf->fileht) == 1) { /* first one, register the cleanup */ apr_pool_cleanup_register(cmd->pool, sconf, cleanup_file_cache, apr_pool_cleanup_null); } } new_file->is_mmapped = TRUE; return NULL; static const char *cachefilehandle(cmd_parms *cmd, void *dummy, const char *filename) { #if APR_HAS_SENDFILE cache_the_file(cmd, filename, 0); #else /* MMAP not supported on this platform*/ return NULL; /* Sendfile not supported by this OS */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", fspec); #endif return NULL; } static int file_compare(const void *av, const void *bv) static const char *cachefilemmap(cmd_parms *cmd, void *dummy, const char *filename) { const a_file *a = av; const a_file *b = bv; return strcmp(a->filename, b->filename); #if APR_HAS_MMAP cache_the_file(cmd, filename, 1); #else /* MMAP not supported by this OS */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. MMAP is not supported by this OS", fspec); #endif return NULL; } static void file_cache_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { a_server_config *sconf; a_file *elts; int nelts; /* sort the elements of the main_server, by filename */ sconf = ap_get_module_config(s->module_config, &file_cache_module); elts = (a_file *)sconf->files->elts; nelts = sconf->files->nelts; qsort(elts, nelts, sizeof(a_file), file_compare); /* and make the virtualhosts share the same thing */ for (s = s->next; s; s = s->next) { ap_set_module_config(s->module_config, &file_cache_module, sconf); } /* Hummm, anything to do here? */ } /* If it's one of ours, fill in r->finfo now to avoid extra stat()... this is a Loading @@ -336,22 +285,21 @@ static int file_cache_xlat(request_rec *r) sconf = ap_get_module_config(r->server->module_config, &file_cache_module); /* we only operate when at least one cachefile directive was used */ if (apr_is_empty_table(sconf->files)) if (!apr_hash_count(sconf->fileht)) { return DECLINED; } res = ap_core_translate(r); if (res != OK || !r->filename) { return res; } tmp.filename = r->filename; match = (a_file *)bsearch(&tmp, sconf->files->elts, sconf->files->nelts, sizeof(a_file), file_compare); /* search the cache */ match = (a_file *) apr_hash_get(sconf->fileht, r->filename, APR_HASH_KEY_STRING); if (match == NULL) return DECLINED; /* pass bsearch results to handler */ /* pass search results to handler */ ap_set_module_config(r->request_config, &file_cache_module, match); /* shortcircuit the get_path_info() stat() calls and stuff */ Loading @@ -359,7 +307,6 @@ static int file_cache_xlat(request_rec *r) return OK; } static int mmap_handler(request_rec *r, a_file *file) { #if APR_HAS_MMAP Loading Loading @@ -481,9 +428,9 @@ static int file_cache_handler(request_rec *r) static command_rec file_cache_cmds[] = { AP_INIT_ITERATE("cachefile", cachefile, NULL, RSRC_CONF, AP_INIT_ITERATE("cachefile", cachefilehandle, NULL, RSRC_CONF, "A space separated list of files to add to the file handle cache at config time"), AP_INIT_ITERATE("mmapfile", mmapfile, NULL, RSRC_CONF, AP_INIT_ITERATE("mmapfile", cachefilemmap, NULL, RSRC_CONF, "A space separated list of files to mmap at config time"), {NULL} }; Loading Loading
modules/cache/mod_file_cache.c +72 −125 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ #include "apr.h" #include "apr_mmap.h" #include "apr_strings.h" #include "apr_hash.h" #define APR_WANT_STRFUNC #include "apr_want.h" Loading Loading @@ -143,7 +144,7 @@ typedef struct { } a_file; typedef struct { apr_array_header_t *files; apr_hash_t *fileht; } a_server_config; Loading @@ -151,176 +152,124 @@ static void *create_server_config(apr_pool_t *p, server_rec *s) { a_server_config *sconf = apr_palloc(p, sizeof(*sconf)); sconf->files = apr_array_make(p, 20, sizeof(a_file)); sconf->fileht = apr_hash_make(p); return sconf; } static apr_status_t cleanup_file_cache(void *sconfv) { a_server_config *sconf = sconfv; size_t n; a_file *file; apr_hash_index_t *hi; n = sconf->files->nelts; file = (a_file *)sconf->files->elts; while(n) { /* Iterate over the file hash table and clean up each entry */ for (hi = apr_hash_first(sconf->fileht); hi; hi=apr_hash_next(hi)) { apr_hash_this(hi, NULL, NULL, &file); #if APR_HAS_MMAP if (file->is_mmapped) { apr_mmap_delete(file->mm); } else #endif #if APR_HAS_SENDFILE if (!file->is_mmapped) { apr_file_close(file->file); } #endif ++file; --n; } return APR_SUCCESS; } static const char *cachefile(cmd_parms *cmd, void *dummy, const char *filename) static void cache_the_file(cmd_parms *cmd, const char *filename, int mmap) { /* ToDo: * Disable the file cache on a Windows 9X box. APR_HAS_SENDFILE will be * defined in an Apache for Windows build, but apr_sendfile returns * APR_ENOTIMPL on Windows 9X because TransmitFile is not available. */ #if APR_HAS_SENDFILE a_server_config *sconf; a_file *new_file; a_file tmp; apr_file_t *fd = NULL; apr_status_t rc; const char *fspec; /* canonicalize the file name? */ /* os_canonical... */ /* XXX: uh... yea, or expect them to be -very- accurate typists */ if ((rc = apr_stat(&tmp.finfo, filename, APR_FINFO_MIN, fspec = ap_os_case_canonical_filename(cmd->pool, filename); if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to stat(%s), skipping", filename); return NULL; "mod_file_cache: unable to stat(%s), skipping", fspec); return; } if (tmp.finfo.filetype != APR_REG) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: %s isn't a regular file, skipping", filename); return NULL; "mod_file_cache: %s isn't a regular file, skipping", fspec); return; } rc = apr_file_open(&fd, filename, APR_READ | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool); rc = apr_file_open(&fd, fspec, APR_READ | APR_XTHREAD, APR_OS_DEFAULT, cmd->pool); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to open(%s, O_RDONLY), skipping", filename); return NULL; } tmp.file = fd; tmp.filename = apr_pstrdup(cmd->pool, filename); apr_rfc822_date(tmp.mtimestr, tmp.finfo.mtime); apr_snprintf(tmp.sizestr, sizeof tmp.sizestr, "%" APR_OFF_T_FMT, tmp.finfo.size); sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module); new_file = apr_array_push(sconf->files); *new_file = tmp; if (sconf->files->nelts == 1) { /* first one, register the cleanup */ apr_pool_cleanup_register(cmd->pool, sconf, cleanup_file_cache, apr_pool_cleanup_null); "mod_file_cache: unable to open(%s, O_RDONLY), skipping", fspec); return; } new_file->is_mmapped = FALSE; /* WooHoo, we have a file to put in the cache */ new_file = apr_pcalloc(cmd->pool, sizeof(a_file)); new_file->finfo = tmp.finfo; return NULL; #else /* Sendfile not supported on this platform */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", filename); return NULL; #endif } static const char *mmapfile(cmd_parms *cmd, void *dummy, const char *filename) { #if APR_HAS_MMAP a_server_config *sconf; a_file *new_file; a_file tmp; apr_file_t *fd = NULL; apr_status_t rc; const char *fspec; fspec = ap_os_case_canonical_filename(cmd->pool, filename); if ((rc = apr_stat(&tmp.finfo, fspec, APR_FINFO_MIN, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to stat(%s), skipping", filename); return NULL; } if ((tmp.finfo.filetype) != APR_REG) { ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: %s isn't a regular file, skipping", filename); return NULL; } if ((rc = apr_file_open(&fd, fspec, APR_READ, APR_OS_DEFAULT, cmd->temp_pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to open %s, skipping", filename); return NULL; } if ((rc = apr_mmap_create(&tmp.mm, fd, 0, tmp.finfo.size, APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) { if (mmap) { /* MMAPFile directive. MMAP'ing the file */ if ((rc = apr_mmap_create(&new_file->mm, fd, 0, new_file->finfo.size, APR_MMAP_READ, cmd->pool)) != APR_SUCCESS) { apr_file_close(fd); ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server, "mod_file_cache: unable to mmap %s, skipping", filename); return NULL; return; } apr_file_close(fd); tmp.filename = fspec; apr_rfc822_date(tmp.mtimestr, tmp.finfo.mtime); apr_snprintf(tmp.sizestr, sizeof tmp.sizestr, "%" APR_OFF_T_FMT, tmp.finfo.size); new_file->is_mmapped = TRUE; } else { /* CacheFile directive. Caching the file handle */ new_file->is_mmapped = FALSE; new_file->file = fd; } new_file->filename = fspec; apr_rfc822_date(new_file->mtimestr, new_file->finfo.mtime); apr_snprintf(new_file->sizestr, sizeof new_file->sizestr, "%" APR_OFF_T_FMT, new_file->finfo.size); sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module); new_file = apr_array_push(sconf->files); *new_file = tmp; if (sconf->files->nelts == 1) { apr_hash_set(sconf->fileht, new_file->filename, strlen(new_file->filename), new_file); if (apr_hash_count(sconf->fileht) == 1) { /* first one, register the cleanup */ apr_pool_cleanup_register(cmd->pool, sconf, cleanup_file_cache, apr_pool_cleanup_null); } } new_file->is_mmapped = TRUE; return NULL; static const char *cachefilehandle(cmd_parms *cmd, void *dummy, const char *filename) { #if APR_HAS_SENDFILE cache_the_file(cmd, filename, 0); #else /* MMAP not supported on this platform*/ return NULL; /* Sendfile not supported by this OS */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", fspec); #endif return NULL; } static int file_compare(const void *av, const void *bv) static const char *cachefilemmap(cmd_parms *cmd, void *dummy, const char *filename) { const a_file *a = av; const a_file *b = bv; return strcmp(a->filename, b->filename); #if APR_HAS_MMAP cache_the_file(cmd, filename, 1); #else /* MMAP not supported by this OS */ ap_log_error(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, cmd->server, "mod_file_cache: unable to cache file: %s. MMAP is not supported by this OS", fspec); #endif return NULL; } static void file_cache_post_config(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { a_server_config *sconf; a_file *elts; int nelts; /* sort the elements of the main_server, by filename */ sconf = ap_get_module_config(s->module_config, &file_cache_module); elts = (a_file *)sconf->files->elts; nelts = sconf->files->nelts; qsort(elts, nelts, sizeof(a_file), file_compare); /* and make the virtualhosts share the same thing */ for (s = s->next; s; s = s->next) { ap_set_module_config(s->module_config, &file_cache_module, sconf); } /* Hummm, anything to do here? */ } /* If it's one of ours, fill in r->finfo now to avoid extra stat()... this is a Loading @@ -336,22 +285,21 @@ static int file_cache_xlat(request_rec *r) sconf = ap_get_module_config(r->server->module_config, &file_cache_module); /* we only operate when at least one cachefile directive was used */ if (apr_is_empty_table(sconf->files)) if (!apr_hash_count(sconf->fileht)) { return DECLINED; } res = ap_core_translate(r); if (res != OK || !r->filename) { return res; } tmp.filename = r->filename; match = (a_file *)bsearch(&tmp, sconf->files->elts, sconf->files->nelts, sizeof(a_file), file_compare); /* search the cache */ match = (a_file *) apr_hash_get(sconf->fileht, r->filename, APR_HASH_KEY_STRING); if (match == NULL) return DECLINED; /* pass bsearch results to handler */ /* pass search results to handler */ ap_set_module_config(r->request_config, &file_cache_module, match); /* shortcircuit the get_path_info() stat() calls and stuff */ Loading @@ -359,7 +307,6 @@ static int file_cache_xlat(request_rec *r) return OK; } static int mmap_handler(request_rec *r, a_file *file) { #if APR_HAS_MMAP Loading Loading @@ -481,9 +428,9 @@ static int file_cache_handler(request_rec *r) static command_rec file_cache_cmds[] = { AP_INIT_ITERATE("cachefile", cachefile, NULL, RSRC_CONF, AP_INIT_ITERATE("cachefile", cachefilehandle, NULL, RSRC_CONF, "A space separated list of files to add to the file handle cache at config time"), AP_INIT_ITERATE("mmapfile", mmapfile, NULL, RSRC_CONF, AP_INIT_ITERATE("mmapfile", cachefilemmap, NULL, RSRC_CONF, "A space separated list of files to mmap at config time"), {NULL} }; Loading