You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Bill Stoddard <st...@raleigh.ibm.com> on 2000/02/04 20:58:56 UTC
[PATCH] mod_mmap_static hacking (caching file handles on Windows NT)
It would help to include the patch :-) Here it is...
Index: mod_mmap_static.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/modules/experimental/mod_mmap_static.c,v
retrieving revision 1.6
diff -u -r1.6 mod_mmap_static.c
--- mod_mmap_static.c 2000/01/04 19:00:56 1.6
+++ mod_mmap_static.c 2000/02/04 19:34:03
@@ -123,13 +123,18 @@
#include "apr_mmap.h"
module MODULE_VAR_EXPORT mmap_static_module;
+static ap_context_t *context;
+static int once_through = 0;
typedef struct {
+#ifdef WIN32
+ ap_file_t *file;
+#else
ap_mmap_t *mm;
+#endif
char *filename;
- struct stat finfo;
+ ap_finfo_t finfo;
} a_file;
-ap_context_t *context;
typedef struct {
ap_array_header_t *files;
@@ -145,7 +150,36 @@
sconf->inode_sorted = NULL;
return sconf;
}
+static void pre_config(ap_context_t *pconf, ap_context_t *plog,
ap_context_t *ptemp)
+{
+ context = pconf;
+}
+static ap_status_t open_file(ap_file_t **file, char* filename, int flg1,
int flg2,
+ ap_context_t *context)
+{
+ ap_status_t rv;
+#ifndef WIN32
+ rv = ap_open(file, filename, flg1, flg2, context);
+#else
+ HANDLE hFile;
+ hFile = CreateFile(filename, // pointer to name of the file
+ GENERIC_READ, // access (read-write) mode
+ FILE_SHARE_READ, // share mode
+ NULL, // pointer to security attributes
+ OPEN_EXISTING, // how to create
+ 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);
+ else {
+ rv = GetLastError();
+ *file = NULL;
+ }
+#endif
+ return rv;
+}
+
ap_status_t cleanup_mmap(void *sconfv)
{
a_server_config *sconf = sconfv;
@@ -155,9 +189,13 @@
n = sconf->files->nelts;
file = (a_file *)sconf->files->elts;
while(n) {
- ap_mmap_delete(file->mm);
- ++file;
- --n;
+#ifdef WIN32
+ ap_close(file->file);
+#else
+ ap_mmap_delete(file->mm);
+#endif
+ ++file;
+ --n;
}
return APR_SUCCESS;
}
@@ -168,23 +206,33 @@
a_file *new_file;
a_file tmp;
ap_file_t *fd = NULL;
+#ifndef WIN32
caddr_t mm;
-
- if (stat(filename, &tmp.finfo) == -1) {
+#endif
+ ap_status_t rc;
+ /* 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,
"mmap_static: unable to stat(%s), skipping", filename);
return NULL;
}
- if ((tmp.finfo.st_mode & S_IFMT) != S_IFREG) {
+ if (tmp.finfo.filetype != APR_REG) {
ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
"mmap_static: %s isn't a regular file, skipping", filename);
return NULL;
}
- if (ap_open(&fd, filename, APR_READ, APR_OS_DEFAULT, context) !=
APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
- "mmap_static: unable to open(%s, O_RDONLY), skipping", filename);
+ /* Note: open_file should call ap_open for Unix and CreateFile for
Windows.
+ * The Windows file needs to be opened for async I/O to allow multiple
threads
+ * to serve it up at once.
+ */
+ rc = open_file(&fd, filename, APR_READ, APR_OS_DEFAULT, context);
+ if (rc != APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
+ "mmap_static: unable to open(%s, O_RDONLY), skipping",
filename);
return NULL;
}
+#ifndef WIN32
if (ap_mmap_create(&tmp.mm, fd, 0, tmp.finfo.st_size, context) !=
APR_SUCCESS) {
int save_errno = errno;
ap_close(fd);
@@ -194,6 +242,9 @@
return NULL;
}
ap_close(fd);
+#else
+ tmp.file = fd;
+#endif
tmp.filename = ap_pstrdup(cmd->pool, filename);
sconf = ap_get_module_config(cmd->server->module_config,
&mmap_static_module);
new_file = ap_push_array(sconf->files);
@@ -205,6 +256,7 @@
return NULL;
}
+#ifdef WIN32
static int file_compare(const void *av, const void *bv)
{
const a_file *a = av;
@@ -212,7 +264,7 @@
return strcmp(a->filename, b->filename);
}
-
+#else
static int inode_compare(const void *av, const void *bv)
{
const a_file *a = *(a_file **)av;
@@ -225,9 +277,9 @@
}
return c;
}
-
+#endif
static void mmap_post_config(ap_context_t *p, ap_context_t *plog,
- ap_context_t *ptemp, server_rec *s)
+ ap_context_t *ptemp, server_rec *s)
{
a_server_config *sconf;
ap_array_header_t *inodes;
@@ -243,13 +295,14 @@
qsort(elts, nelts, sizeof(a_file), file_compare);
/* build an index by inode as well, speeds up the search in the handler
*/
+#ifndef WIN32
inodes = ap_make_array(p, nelts, sizeof(a_file *));
sconf->inode_sorted = inodes;
for (i = 0; i < nelts; ++i) {
*(a_file **)ap_push_array(inodes) = &elts[i];
}
qsort(inodes->elts, nelts, sizeof(a_file *), inode_compare);
-
+#endif
/* and make the virtualhosts share the same thing */
for (s = s->next; s; s = s->next) {
ap_set_module_config(s->module_config, &mmap_static_module, sconf);
@@ -259,7 +312,47 @@
/* If it's one of ours, fill in r->finfo now to avoid extra stat()... this
is a
* bit of a kludge, because we really want to run after core_translate
runs.
*/
-
+int core_translate_copy(request_rec *r)
+{
+ void *sconf = r->server->module_config;
+ core_server_config *conf = ap_get_module_config(sconf, &core_module);
+
+ if (r->proxyreq) {
+ return HTTP_FORBIDDEN;
+ }
+ if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
+ ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ "Invalid URI in request %s", r->the_request);
+ return BAD_REQUEST;
+ }
+
+ if (r->server->path
+ && !strncmp(r->uri, r->server->path, r->server->pathlen)
+ && (r->server->path[r->server->pathlen - 1] == '/'
+ || r->uri[r->server->pathlen] == '/'
+ || r->uri[r->server->pathlen] == '\0')) {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
+ (r->uri + r->server->pathlen), NULL);
+ }
+ else {
+ /*
+ * Make sure that we do not mess up the translation by adding two
+ * /'s in a row. This happens under windows when the document
+ * root ends with a /
+ */
+ if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] ==
'/')
+ && (*(r->uri) == '/')) {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
r->uri+1,
+ NULL);
+ }
+ else {
+ r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
r->uri,
+ NULL);
+ }
+
+ return OK;
+ }
+}
static int mmap_static_xlat(request_rec *r)
{
a_server_config *sconf;
@@ -273,10 +366,12 @@
if (ap_is_empty_table(sconf->files))
return DECLINED;
-/* res = core_module.translate_handler(r);
+/* res = core_module.translate_handler(r); */
+ res = core_translate_copy(r);
if (res == DECLINED || !r->filename) {
return res;
- }*/
+ }
+
if (!r->filename)
return DECLINED;
tmp.filename = r->filename;
@@ -299,23 +394,38 @@
a_file **pmatch;
a_file *match;
int rangestatus, errstatus;
+#ifdef WIN32
+ HANDLE hCurrentProcess;
+#endif
/* we don't handle anything but GET */
if (r->method_number != M_GET) return DECLINED;
/* file doesn't exist, we won't be dealing with it */
- if (r->finfo.st_mode == 0) return DECLINED;
+ if (r->finfo.protection == 0) return DECLINED;
sconf = ap_get_module_config(r->server->module_config,
&mmap_static_module);
+#ifdef WIN32
+ tmp.filename = r->filename;
+#else
tmp.finfo.st_dev = r->finfo.st_dev;
tmp.finfo.st_ino = r->finfo.st_ino;
+#endif
ptmp = &tmp;
+#ifdef WIN32
+ match = (a_file *)bsearch(ptmp, sconf->files->elts,
+ sconf->files->nelts, sizeof(a_file), file_compare);
+ if (match == NULL) {
+ return DECLINED;
+ }
+#else
pmatch = (a_file **)bsearch(&ptmp, sconf->inode_sorted->elts,
sconf->inode_sorted->nelts, sizeof(a_file *), inode_compare);
if (pmatch == NULL) {
return DECLINED;
}
match = *pmatch;
+#endif
/* note that we would handle GET on this resource */
r->allowed |= (1 << M_GET);
@@ -326,11 +436,11 @@
if ((errstatus = ap_discard_request_body(r)) != OK)
return errstatus;
- ap_update_mtime(r, match->finfo.st_mtime);
+ ap_update_mtime(r, match->finfo.mtime);
ap_set_last_modified(r);
ap_set_etag(r);
if (((errstatus = ap_meets_conditions(r)) != OK)
- || (errstatus = ap_set_content_length (r, match->finfo.st_size))) {
+ || (errstatus = ap_set_content_length (r, match->finfo.size))) {
return errstatus;
}
@@ -338,16 +448,53 @@
ap_send_http_header(r);
if (!r->header_only) {
+ long length = match->finfo.size;
+ ap_off_t offset = 0;
+#ifdef WIN32
+// ap_bflush(r->connection->client->);
+ struct iovec iov;
+ ap_hdtr_t hdtr;
+ ap_hdtr_t *phdtr = &hdtr;
+ /* frob the client buffer */
+ 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;
+ }
+ }
+#else
if (!rangestatus) {
ap_send_mmap (match->mm, r, 0, match->finfo.st_size);
}
else {
- long length;
- ap_off_t offset;
while (ap_each_byterange(r, &offset, &length)) {
ap_send_mmap(match->mm, r, offset, length);
}
}
+#endif
}
return OK;
}
@@ -362,8 +509,9 @@
static void register_hooks(void)
{
static const char* const aszPre[]={"http_core.c",NULL};
+ ap_hook_pre_config(pre_config,NULL,NULL,HOOK_MIDDLE);
ap_hook_post_config(mmap_post_config, NULL, NULL, HOOK_MIDDLE);
- ap_hook_translate_name(mmap_static_xlat, aszPre, NULL, HOOK_LAST);
+ ap_hook_translate_name(mmap_static_xlat, aszPre, NULL, HOOK_MIDDLE);
};
static const handler_rec mmap_static_handlers[] =
Re: [PATCH] mod_mmap_static hacking (caching file handles on Windows NT)
Posted by David Reid <ab...@dial.pipex.com>.
It was suggested a while back that we split the directory structure a little
to have specific modules for platforms. Maybe we should do it now and copy
all modules into both? It shouldn't take long for a few volunteers to strip
out non-platform code.
david
----- Original Message -----
From: "Bill Stoddard" <st...@raleigh.ibm.com>
To: <ne...@apache.org>
Sent: Friday, February 04, 2000 7:58 PM
Subject: [PATCH] mod_mmap_static hacking (caching file handles on Windows
NT)
> It would help to include the patch :-) Here it is...
>
> Index: mod_mmap_static.c
> ===================================================================
> RCS file:
/home/cvs/apache-2.0/src/modules/experimental/mod_mmap_static.c,v
> retrieving revision 1.6
> diff -u -r1.6 mod_mmap_static.c
> --- mod_mmap_static.c 2000/01/04 19:00:56 1.6
> +++ mod_mmap_static.c 2000/02/04 19:34:03
> @@ -123,13 +123,18 @@
> #include "apr_mmap.h"
>
> module MODULE_VAR_EXPORT mmap_static_module;
> +static ap_context_t *context;
> +static int once_through = 0;
>
> typedef struct {
> +#ifdef WIN32
> + ap_file_t *file;
> +#else
> ap_mmap_t *mm;
> +#endif
> char *filename;
> - struct stat finfo;
> + ap_finfo_t finfo;
> } a_file;
> -ap_context_t *context;
>
> typedef struct {
> ap_array_header_t *files;
> @@ -145,7 +150,36 @@
> sconf->inode_sorted = NULL;
> return sconf;
> }
> +static void pre_config(ap_context_t *pconf, ap_context_t *plog,
> ap_context_t *ptemp)
> +{
> + context = pconf;
> +}
> +static ap_status_t open_file(ap_file_t **file, char* filename, int flg1,
> int flg2,
> + ap_context_t *context)
> +{
> + ap_status_t rv;
> +#ifndef WIN32
> + rv = ap_open(file, filename, flg1, flg2, context);
> +#else
> + HANDLE hFile;
> + hFile = CreateFile(filename, // pointer to name of the file
> + GENERIC_READ, // access (read-write) mode
> + FILE_SHARE_READ, // share mode
> + NULL, // pointer to security
attributes
> + OPEN_EXISTING, // how to create
> + 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);
> + else {
> + rv = GetLastError();
> + *file = NULL;
> + }
>
> +#endif
> + return rv;
> +}
> +
> ap_status_t cleanup_mmap(void *sconfv)
> {
> a_server_config *sconf = sconfv;
> @@ -155,9 +189,13 @@
> n = sconf->files->nelts;
> file = (a_file *)sconf->files->elts;
> while(n) {
> - ap_mmap_delete(file->mm);
> - ++file;
> - --n;
> +#ifdef WIN32
> + ap_close(file->file);
> +#else
> + ap_mmap_delete(file->mm);
> +#endif
> + ++file;
> + --n;
> }
> return APR_SUCCESS;
> }
> @@ -168,23 +206,33 @@
> a_file *new_file;
> a_file tmp;
> ap_file_t *fd = NULL;
> +#ifndef WIN32
> caddr_t mm;
> -
> - if (stat(filename, &tmp.finfo) == -1) {
> +#endif
> + ap_status_t rc;
> + /* 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,
> "mmap_static: unable to stat(%s), skipping", filename);
> return NULL;
> }
> - if ((tmp.finfo.st_mode & S_IFMT) != S_IFREG) {
> + if (tmp.finfo.filetype != APR_REG) {
> ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
> "mmap_static: %s isn't a regular file, skipping", filename);
> return NULL;
> }
> - if (ap_open(&fd, filename, APR_READ, APR_OS_DEFAULT, context) !=
> APR_SUCCESS) {
> - ap_log_error(APLOG_MARK, APLOG_WARNING, errno, cmd->server,
> - "mmap_static: unable to open(%s, O_RDONLY), skipping", filename);
> + /* Note: open_file should call ap_open for Unix and CreateFile for
> Windows.
> + * The Windows file needs to be opened for async I/O to allow
multiple
> threads
> + * to serve it up at once.
> + */
> + rc = open_file(&fd, filename, APR_READ, APR_OS_DEFAULT, context);
> + if (rc != APR_SUCCESS) {
> + ap_log_error(APLOG_MARK, APLOG_WARNING, rc, cmd->server,
> + "mmap_static: unable to open(%s, O_RDONLY),
skipping",
> filename);
> return NULL;
> }
> +#ifndef WIN32
> if (ap_mmap_create(&tmp.mm, fd, 0, tmp.finfo.st_size, context) !=
> APR_SUCCESS) {
> int save_errno = errno;
> ap_close(fd);
> @@ -194,6 +242,9 @@
> return NULL;
> }
> ap_close(fd);
> +#else
> + tmp.file = fd;
> +#endif
> tmp.filename = ap_pstrdup(cmd->pool, filename);
> sconf = ap_get_module_config(cmd->server->module_config,
> &mmap_static_module);
> new_file = ap_push_array(sconf->files);
> @@ -205,6 +256,7 @@
> return NULL;
> }
>
> +#ifdef WIN32
> static int file_compare(const void *av, const void *bv)
> {
> const a_file *a = av;
> @@ -212,7 +264,7 @@
>
> return strcmp(a->filename, b->filename);
> }
> -
> +#else
> static int inode_compare(const void *av, const void *bv)
> {
> const a_file *a = *(a_file **)av;
> @@ -225,9 +277,9 @@
> }
> return c;
> }
> -
> +#endif
> static void mmap_post_config(ap_context_t *p, ap_context_t *plog,
> - ap_context_t *ptemp, server_rec *s)
> + ap_context_t *ptemp, server_rec *s)
> {
> a_server_config *sconf;
> ap_array_header_t *inodes;
> @@ -243,13 +295,14 @@
> qsort(elts, nelts, sizeof(a_file), file_compare);
>
> /* build an index by inode as well, speeds up the search in the
handler
> */
> +#ifndef WIN32
> inodes = ap_make_array(p, nelts, sizeof(a_file *));
> sconf->inode_sorted = inodes;
> for (i = 0; i < nelts; ++i) {
> *(a_file **)ap_push_array(inodes) = &elts[i];
> }
> qsort(inodes->elts, nelts, sizeof(a_file *), inode_compare);
> -
> +#endif
> /* and make the virtualhosts share the same thing */
> for (s = s->next; s; s = s->next) {
> ap_set_module_config(s->module_config, &mmap_static_module, sconf);
> @@ -259,7 +312,47 @@
> /* If it's one of ours, fill in r->finfo now to avoid extra stat()...
this
> is a
> * bit of a kludge, because we really want to run after core_translate
> runs.
> */
> -
> +int core_translate_copy(request_rec *r)
> +{
> + void *sconf = r->server->module_config;
> + core_server_config *conf = ap_get_module_config(sconf, &core_module);
> +
> + if (r->proxyreq) {
> + return HTTP_FORBIDDEN;
> + }
> + if ((r->uri[0] != '/') && strcmp(r->uri, "*")) {
> + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
> + "Invalid URI in request %s", r->the_request);
> + return BAD_REQUEST;
> + }
> +
> + if (r->server->path
> + && !strncmp(r->uri, r->server->path, r->server->pathlen)
> + && (r->server->path[r->server->pathlen - 1] == '/'
> + || r->uri[r->server->pathlen] == '/'
> + || r->uri[r->server->pathlen] == '\0')) {
> + r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
> + (r->uri + r->server->pathlen), NULL);
> + }
> + else {
> + /*
> + * Make sure that we do not mess up the translation by adding two
> + * /'s in a row. This happens under windows when the document
> + * root ends with a /
> + */
> + if ((conf->ap_document_root[strlen(conf->ap_document_root)-1] ==
> '/')
> + && (*(r->uri) == '/')) {
> + r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
> r->uri+1,
> + NULL);
> + }
> + else {
> + r->filename = ap_pstrcat(r->pool, conf->ap_document_root,
> r->uri,
> + NULL);
> + }
> +
> + return OK;
> + }
> +}
> static int mmap_static_xlat(request_rec *r)
> {
> a_server_config *sconf;
> @@ -273,10 +366,12 @@
> if (ap_is_empty_table(sconf->files))
> return DECLINED;
>
> -/* res = core_module.translate_handler(r);
> +/* res = core_module.translate_handler(r); */
> + res = core_translate_copy(r);
> if (res == DECLINED || !r->filename) {
> return res;
> - }*/
> + }
> +
> if (!r->filename)
> return DECLINED;
> tmp.filename = r->filename;
> @@ -299,23 +394,38 @@
> a_file **pmatch;
> a_file *match;
> int rangestatus, errstatus;
> +#ifdef WIN32
> + HANDLE hCurrentProcess;
> +#endif
>
> /* we don't handle anything but GET */
> if (r->method_number != M_GET) return DECLINED;
>
> /* file doesn't exist, we won't be dealing with it */
> - if (r->finfo.st_mode == 0) return DECLINED;
> + if (r->finfo.protection == 0) return DECLINED;
>
> sconf = ap_get_module_config(r->server->module_config,
> &mmap_static_module);
> +#ifdef WIN32
> + tmp.filename = r->filename;
> +#else
> tmp.finfo.st_dev = r->finfo.st_dev;
> tmp.finfo.st_ino = r->finfo.st_ino;
> +#endif
> ptmp = &tmp;
> +#ifdef WIN32
> + match = (a_file *)bsearch(ptmp, sconf->files->elts,
> + sconf->files->nelts, sizeof(a_file), file_compare);
> + if (match == NULL) {
> + return DECLINED;
> + }
> +#else
> pmatch = (a_file **)bsearch(&ptmp, sconf->inode_sorted->elts,
> sconf->inode_sorted->nelts, sizeof(a_file *), inode_compare);
> if (pmatch == NULL) {
> return DECLINED;
> }
> match = *pmatch;
> +#endif
>
> /* note that we would handle GET on this resource */
> r->allowed |= (1 << M_GET);
> @@ -326,11 +436,11 @@
> if ((errstatus = ap_discard_request_body(r)) != OK)
> return errstatus;
>
> - ap_update_mtime(r, match->finfo.st_mtime);
> + ap_update_mtime(r, match->finfo.mtime);
> ap_set_last_modified(r);
> ap_set_etag(r);
> if (((errstatus = ap_meets_conditions(r)) != OK)
> - || (errstatus = ap_set_content_length (r, match->finfo.st_size))) {
> + || (errstatus = ap_set_content_length (r, match->finfo.size))) {
> return errstatus;
> }
>
> @@ -338,16 +448,53 @@
> ap_send_http_header(r);
>
> if (!r->header_only) {
> + long length = match->finfo.size;
> + ap_off_t offset = 0;
> +#ifdef WIN32
> +// ap_bflush(r->connection->client->);
> + struct iovec iov;
> + ap_hdtr_t hdtr;
> + ap_hdtr_t *phdtr = &hdtr;
> + /* frob the client buffer */
> + 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;
> + }
> + }
> +#else
> if (!rangestatus) {
> ap_send_mmap (match->mm, r, 0, match->finfo.st_size);
> }
> else {
> - long length;
> - ap_off_t offset;
> while (ap_each_byterange(r, &offset, &length)) {
> ap_send_mmap(match->mm, r, offset, length);
> }
> }
> +#endif
> }
> return OK;
> }
> @@ -362,8 +509,9 @@
> static void register_hooks(void)
> {
> static const char* const aszPre[]={"http_core.c",NULL};
> + ap_hook_pre_config(pre_config,NULL,NULL,HOOK_MIDDLE);
> ap_hook_post_config(mmap_post_config, NULL, NULL, HOOK_MIDDLE);
> - ap_hook_translate_name(mmap_static_xlat, aszPre, NULL, HOOK_LAST);
> + ap_hook_translate_name(mmap_static_xlat, aszPre, NULL, HOOK_MIDDLE);
> };
>
> static const handler_rec mmap_static_handlers[] =
>
>
>