httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Bill Stoddard" <stodd...@raleigh.ibm.com>
Subject [PATCH] mod_mmap_static hacking (caching file handles on Windows NT)
Date Fri, 04 Feb 2000 19:58:56 GMT
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[] =




Mime
View raw message