From: Bill Stoddard Date: Mon, 26 Mar 2001 18:01:17 +0000 (+0000) Subject: Eat our own cooking. Cleanup code paths and use apr_hash functions. Good X-Git-Tag: 2.0.16~69 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b951f8b0c7ee76128b07836322dcaa2c0e7d2597;p=apache Eat our own cooking. Cleanup code paths and use apr_hash functions. Good for a small performance boost. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88586 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/cache/mod_file_cache.c b/modules/cache/mod_file_cache.c index 697f676533..5602a6c851 100644 --- a/modules/cache/mod_file_cache.c +++ b/modules/cache/mod_file_cache.c @@ -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" @@ -143,7 +144,7 @@ typedef struct { } a_file; typedef struct { - apr_array_header_t *files; + apr_hash_t *fileht; } a_server_config; @@ -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; + "mod_file_cache: unable to open(%s, O_RDONLY), skipping", fspec); + return; } - 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); + + /* WooHoo, we have a file to put in the cache */ + new_file = apr_pcalloc(cmd->pool, sizeof(a_file)); + new_file->finfo = tmp.finfo; + + 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; + } + apr_file_close(fd); + 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 = FALSE; - - 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 - /* Sendfile not supported on this platform */ + /* 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", filename); - return NULL; + "mod_file_cache: unable to cache file: %s. Sendfile is not supported on this OS", fspec); #endif + return NULL; } - -static const char *mmapfile(cmd_parms *cmd, void *dummy, const char *filename) +static const char *cachefilemmap(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) { - 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; - } - 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); - 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); - } - - new_file->is_mmapped = TRUE; - - return NULL; + cache_the_file(cmd, filename, 1); #else - /* MMAP not supported on this platform*/ - return NULL; + /* 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 -} - - -static int file_compare(const void *av, const void *bv) -{ - const a_file *a = av; - const a_file *b = bv; - - return strcmp(a->filename, b->filename); + 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 @@ -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 */ @@ -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 @@ -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} };