]> granicus.if.org Git - apache/commitdiff
Eat our own cooking. Cleanup code paths and use apr_hash functions. Good
authorBill Stoddard <stoddard@apache.org>
Mon, 26 Mar 2001 18:01:17 +0000 (18:01 +0000)
committerBill Stoddard <stoddard@apache.org>
Mon, 26 Mar 2001 18:01:17 +0000 (18:01 +0000)
for a small performance boost.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88586 13f79535-47bb-0310-9956-ffa450edef68

modules/cache/mod_file_cache.c

index 697f67653307b097249429e8833d558c645ffdf1..5602a6c8510aa24697382aa715bf2038e6dcd657 100644 (file)
 #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}
 };