httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "David Reid" <ab...@dial.pipex.com>
Subject Re: [PATCH] mod_mmap_static hacking (caching file handles on Windows NT)
Date Fri, 04 Feb 2000 22:23:35 GMT
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" <stoddard@raleigh.ibm.com>
To: <new-httpd@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[] =
>
>
>


Mime
View raw message