Return-Path: Delivered-To: apmail-apache-cvs-archive@apache.org Received: (qmail 88493 invoked by uid 500); 28 Jun 2000 19:20:23 -0000 Mailing-List: contact apache-cvs-help@apache.org; run by ezmlm Precedence: bulk X-No-Archive: yes Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list apache-cvs@apache.org Received: (qmail 88397 invoked by uid 500); 28 Jun 2000 19:20:11 -0000 Delivered-To: apmail-apache-2.0-cvs@apache.org Date: 28 Jun 2000 19:20:03 -0000 Message-ID: <20000628192003.88353.qmail@locus.apache.org> From: stoddard@locus.apache.org To: apache-2.0-cvs@apache.org Subject: cvs commit: apache-2.0/src/modules/standard mod_file_cache.c stoddard 00/06/28 12:20:00 Modified: src/modules/standard mod_file_cache.c Log: First cut at getting mod_mmap_static function into mod_file_cache. My intent is to retire mod_mmap_static. Revision Changes Path 1.11 +170 -60 apache-2.0/src/modules/standard/mod_file_cache.c Index: mod_file_cache.c =================================================================== RCS file: /home/cvs/apache-2.0/src/modules/standard/mod_file_cache.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- mod_file_cache.c 2000/06/28 14:46:01 1.10 +++ mod_file_cache.c 2000/06/28 19:19:46 1.11 @@ -118,9 +118,6 @@ #ifdef HAVE_STRING_H #include #endif -/* What are these here for? rbb */ -#include -#include #define CORE_PRIVATE @@ -133,18 +130,18 @@ #include "apr_mmap.h" module MODULE_VAR_EXPORT file_cache_module; -static ap_pool_t *context; +static ap_pool_t *pconf; static int once_through = 0; typedef struct { ap_file_t *file; char *filename; ap_finfo_t finfo; + int is_mmapped; } a_file; typedef struct { ap_array_header_t *files; - ap_array_header_t *inode_sorted; } a_server_config; @@ -153,12 +150,11 @@ a_server_config *sconf = ap_palloc(p, sizeof(*sconf)); sconf->files = ap_make_array(p, 20, sizeof(a_file)); - sconf->inode_sorted = NULL; return sconf; } static ap_status_t open_file(ap_file_t **file, char* filename, int flg1, int flg2, - ap_pool_t *context) + ap_pool_t *p) { ap_status_t rv; #ifdef WIN32 @@ -174,19 +170,20 @@ FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN, /* file attributes */ NULL); /* handle to file with attributes to copy */ if (hFile != INVALID_HANDLE_VALUE) { - rv = ap_put_os_file(file, &hFile, context); + rv = ap_put_os_file(file, &hFile, p); } else { rv = GetLastError(); *file = NULL; } #else - rv = ap_open(file, filename, flg1, flg2, context); + rv = ap_open(file, filename, flg1, flg2, p); #endif return rv; } +#if APR_HAS_SENDFILE ap_status_t cleanup_file_cache(void *sconfv) { a_server_config *sconf = sconfv; @@ -202,16 +199,35 @@ } return APR_SUCCESS; } +#endif +#if APR_HAS_MMAP +static ap_status_t cleanup_mmap(void *sconfv) +{ + a_server_config *sconf = sconfv; + size_t n; + a_file *file; + + n = sconf->files->nelts; + file = (a_file *)sconf->files->elts; + while(n) { + ap_mmap_delete(file->mm); + ++file; + --n; + } + return APR_SUCCESS; +} +#endif static const char *cachefile(cmd_parms *cmd, void *dummy, char *filename) { +#if APR_HAS_SENDFILE a_server_config *sconf; a_file *new_file; a_file tmp; ap_file_t *fd = NULL; ap_status_t rc; - /* canonicalize the file name */ + /* canonicalize the file name? */ /* os_canonical... */ if (ap_stat(&tmp.finfo, filename, NULL) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server, @@ -243,9 +259,69 @@ /* first one, register the cleanup */ ap_register_cleanup(cmd->pool, sconf, cleanup_file_cache, ap_null_cleanup); } + + new_file->is_mmapped = FALSE; + + return NULL; +#else + /* Sendfile not supported on this platform */ + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, 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, char *filename) +{ +#if APR_HAS_MMAP + a_server_config *sconf; + a_file *new_file; + a_file tmp; + ap_file_t *fd = NULL; + + if (ap_stat(&tmp.finfo, filename, pconf) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, 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, errno, cmd->server, + "mod_file_cache: %s isn't a regular file, skipping", filename); + return NULL; + } + if (ap_open(&fd, filename, APR_READ, APR_OS_DEFAULT, pconf) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server, + "mod_file_cache: unable to open(%s, O_RDONLY), skipping", filename); + return NULL; + } + if (ap_mmap_create(&tmp.mm, fd, 0, tmp.finfo.size, pconf) != APR_SUCCESS) { + int save_errno = errno; + ap_close(fd); + errno = save_errno; + ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server, + "mod_file_cache: unable to mmap %s, skipping", filename); + return NULL; + } + ap_close(fd); + tmp.filename = ap_pstrdup(cmd->pool, filename); + sconf = ap_get_module_config(cmd->server->module_config, &file_cache_module); + new_file = ap_push_array(sconf->files); + *new_file = tmp; + if (sconf->files->nelts == 1) { + /* first one, register the cleanup */ + ap_register_cleanup(cmd->pool, sconf, cleanup_mmap, ap_null_cleanup); + } + + new_file->is_mmapped = TRUE; + + return NULL; +#else + /* MMAP not supported on this platform*/ return NULL; +#endif } + static int file_compare(const void *av, const void *bv) { const a_file *a = av; @@ -260,8 +336,10 @@ a_server_config *sconf; a_file *elts; int nelts; + + once_through++; + pconf = p; - context = p; /* 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; @@ -310,11 +388,80 @@ return OK; } + +static int mmap_handler(request_rec *r, a_file *file, int rangestatus) +{ +#if APR_HAS_MMAP + if (!rangestatus) { + ap_send_mmap (file->mm, r, 0, file->finfo.size); + } + else { + long length; + ap_off_t offset; + while (ap_each_byterange(r, &offset, &length)) { + ap_send_mmap(file->mm, r, offset, length); + } + } +#endif + return OK; +} + + +static int sendfile_handler(request_rec *r, a_file *file, int rangestatus) +{ +#if APR_HAS_SENDFILE + long length; + ap_off_t offset = 0; + struct iovec iov; + ap_hdtr_t hdtr; + ap_hdtr_t *phdtr = &hdtr; + + /* + * We want to send any data held in the client buffer on the + * call to iol_sendfile. So hijack it then set outcnt to 0 + * to prevent the data from being sent to the client again + * when the buffer is flushed to the client at the end of the + * request. + */ + iov.iov_base = r->connection->client->outbase; + iov.iov_len = r->connection->client->outcnt; + r->connection->client->outcnt = 0; + + /* initialize the ap_hdtr_t struct */ + phdtr->headers = &iov; + phdtr->numheaders = 1; + phdtr->trailers = NULL; + phdtr->numtrailers = 0; + + if (!rangestatus) { + length = file->finfo.size; + iol_sendfile(r->connection->client->iol, + file->file, + phdtr, + &offset, + &length, + 0); + } + else { + while (ap_each_byterange(r, &offset, &length)) { + iol_sendfile(r->connection->client->iol, + file->file, + phdtr, + &offset, + &length, + 0); + phdtr = NULL; + } + } +#endif + return OK; +} -static int file_cache_handler(request_rec *r) +static int file_cache_handler(request_rec *r) { a_file *match; int rangestatus, errstatus; + int rc = OK; /* we don't handle anything but GET */ if (r->method_number != M_GET) return DECLINED; @@ -346,65 +493,28 @@ rangestatus = ap_set_byterange(r); ap_send_http_header(r); - if (!r->header_only) { - long length = match->finfo.size; - ap_off_t offset = 0; - struct iovec iov; - ap_hdtr_t hdtr; - ap_hdtr_t *phdtr = &hdtr; - - /* - * We want to send any data held in the client buffer on the - * call to iol_sendfile. So hijack it then set outcnt to 0 - * to prevent the data from being sent to the client again - * when the buffer is flushed to the client at the end of the - * request. - */ - iov.iov_base = r->connection->client->outbase; - iov.iov_len = r->connection->client->outcnt; - r->connection->client->outcnt = 0; - - /* initialize the ap_hdtr_t struct */ - phdtr->headers = &iov; - phdtr->numheaders = 1; - phdtr->trailers = NULL; - phdtr->numtrailers = 0; - - if (!rangestatus) { - iol_sendfile(r->connection->client->iol, - match->file, - phdtr, - &offset, - &length, - 0); - } - else { - while (ap_each_byterange(r, &offset, &length)) { - iol_sendfile(r->connection->client->iol, - match->file, - phdtr, - &offset, - &length, - 0); - phdtr = NULL; - } - } + /* Call appropriate handler */ + if (!r->header_only) { + if (match->is_mmapped == TRUE) + rc = mmap_handler(r, match, rangestatus); + else + rc = sendfile_handler(r, match, rangestatus); } - return OK; + return rc; } -static command_rec mmap_cmds[] = +static command_rec file_cache_cmds[] = { {"cachefile", cachefile, NULL, RSRC_CONF, ITERATE, + "A space seperated list of files to add to the file handle cache at config time"}, + {"mmapfile", mmapfile, NULL, RSRC_CONF, ITERATE, "A space seperated list of files to mmap at config time"}, {NULL} }; static void register_hooks(void) { - /* static const char* const aszPre[]={"http_core.c",NULL}; */ - /* ap_hook_pre_config(pre_config,NULL,NULL,AP_HOOK_MIDDLE); */ ap_hook_post_config(file_cache_post_config, NULL, NULL, AP_HOOK_MIDDLE); ap_hook_translate_name(file_cache_xlat, NULL, NULL, AP_HOOK_MIDDLE); /* This trick doesn't work apparently because the translate hooks @@ -428,7 +538,7 @@ NULL, /* merge per-directory config structures */ create_server_config, /* create per-server config structure */ NULL, /* merge per-server config structures */ - mmap_cmds, /* command handlers */ + file_cache_cmds, /* command handlers */ file_cache_handlers, /* handlers */ register_hooks /* register hooks */ };