dgaudet     97/08/18 00:19:39

  Modified:    htdocs/manual new_features_1_3.html
               src      CHANGES PORTING
               src/core conf.h http_core.c http_protocol.c http_protocol.h
  Log:
  Added mmap() support for static files going through default_handler.
  
  Revision  Changes    Path
  1.18      +1 -1      apachen/htdocs/manual/new_features_1_3.html
  
  Index: new_features_1_3.html
  ===================================================================
  RCS file: /export/home/cvs/apachen/htdocs/manual/new_features_1_3.html,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- new_features_1_3.html     1997/08/18 07:17:19     1.17
  +++ new_features_1_3.html     1997/08/18 07:19:30     1.18
  @@ -193,7 +193,7 @@
        to issue multiple writes with a single system call.  They also avoid
        copying memory into buffers as much as possible.  The result is
        less CPU time spent on transferring large files.
  -    <li><i>XXX Incomplete:</i> Static requests are served using
  +    <li>Static requests are served using
        <code>mmap</code>, which means bytes are only copied from the
        disk buffer to the network buffer directly by the kernel.  The
        program never copies bytes around, which reduces CPU time.
  
  
  
  1.404     +7 -0      apachen/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/CHANGES,v
  retrieving revision 1.403
  retrieving revision 1.404
  diff -u -r1.403 -r1.404
  --- CHANGES   1997/08/18 07:17:21     1.403
  +++ CHANGES   1997/08/18 07:19:31     1.404
  @@ -1,5 +1,12 @@
   Changes with Apache 1.3a2
   
  +  *) Various architectures now define USE_MMAP_FILES which causes
  +     the server to use mmap() for static files.  There are two
  +     compile-time tunables MMAP_THRESHOLD (minimum number of bytes
  +     required to use mmap(), default is 0), and MMAP_SEGMENT_SIZE (maximum
  +     number of bytes written in one cycle from a single mmap()d object,
  +     default 32768).  [Dean Gaudet]
  +
     *) API: Added post_read_request API phase which is run right after reading
        the request from a client, or right after an internal redirect.  It is
        useful for modules setting environment variables that depend only on
  
  
  
  1.10      +5 -1      apachen/src/PORTING
  
  Index: PORTING
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/PORTING,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- PORTING   1997/08/09 00:55:53     1.9
  +++ PORTING   1997/08/18 07:19:32     1.10
  @@ -171,7 +171,8 @@
       HAVE_MMAP:
         Define if the OS supports the BSD mmap() call. This is used by various
         OSs to allow the scoreboard file to be held in shared mmapped-memory
  -      instead of a real file.
  +      instead of a real file.  Note that this is only used to determine
  +      if mmap should be used for shared memory.
   
       HAVE_SHMGET:
         Define if the OS has the SysV-based shmget() family of shared-memory
  @@ -213,6 +214,9 @@
        USE_LONGJMP:
         use the longjmp() call instead of siglongjmp()
         (as well as setjmp() instead of sigsetjmp())
  +     
  +     USE_MMAP_FILES:
  +      Enable the use of mmap() for sending static files.
   
   --
   
  
  
  
  1.125     +12 -0     apachen/src/core/conf.h
  
  Index: conf.h
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/core/conf.h,v
  retrieving revision 1.124
  retrieving revision 1.125
  diff -u -r1.124 -r1.125
  --- conf.h    1997/08/17 11:14:34     1.124
  +++ conf.h    1997/08/18 07:19:34     1.125
  @@ -85,6 +85,7 @@
   char *mktemp(char *template);
   #define JMP_BUF sigjmp_buf
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #include <sys/time.h>     
   #define NEED_STRERROR
   typedef int rlim_t;
  @@ -105,6 +106,7 @@
   #define USE_PTHREAD_SERIALIZED_ACCEPT
   #define NEED_UNION_SEMUN
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_CRYPT_H
   int gethostname(char *name, int namelen);
   
  @@ -118,6 +120,7 @@
   /*#define USE_FCNTL_SERIALIZED_ACCEPT*/
   #define USE_SYSVSEM_SERIALIZED_ACCEPT
   #define HAVE_SHMGET
  +#define USE_MMAP_FILES
   #define HAVE_CRYPT_H
   #define NO_LONG_DOUBLE
   #define HAVE_BSTRING_H
  @@ -158,6 +161,7 @@
   #define JMP_BUF sigjmp_buf
   #ifndef __ps2__
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define DEFAULT_GROUP "nobody"
   #endif
   #define DEFAULT_USER "nobody"
  @@ -183,6 +187,7 @@
   #undef NO_SETSID
   #define JMP_BUF sigjmp_buf
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_CRYPT_H
   #define NO_LONG_DOUBLE
   
  @@ -192,6 +197,7 @@
   #undef NO_SETSID
   #define JMP_BUF sigjmp_buf
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_CRYPT_H
   #define NO_LONG_DOUBLE
   typedef int rlim_t;
  @@ -271,6 +277,7 @@
   #define NET_SIZE_T size_t
   #endif
   #define HAVE_SHMGET
  +#define USE_MMAP_FILES
   #define HAVE_SYS_RESOURCE_H
   typedef int rlim_t;
   /* flock is faster ... but hasn't been tested on 1.x systems */
  @@ -302,6 +309,7 @@
   #define HAVE_SYS_SELECT_H
   #define USE_FCNTL_SERIALIZED_ACCEPT
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_SYS_RESOURCE_H
   #define SecureWare
   
  @@ -366,6 +374,7 @@
   #define JMP_BUF sigjmp_buf
   #define HAVE_RESOURCE
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_SHMGET
   #define HAVE_CRYPT_H
   #define HAVE_SYS_SELECT_H
  @@ -421,6 +430,7 @@
   #undef NO_SETSID
   #define JMP_BUF sigjmp_buf
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define DEFAULT_USER "nobody"
   #define DEFAULT_GROUP "nogroup"
   #if defined(__bsdi__) || \
  @@ -469,6 +479,7 @@
   #define JMP_BUF sigjmp_buf
   #define USE_FCNTL_SERIALIZED_ACCEPT
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   #define HAVE_CRYPT_H
    
   #elif defined(__EMX__)
  @@ -510,6 +521,7 @@
   #undef NO_SETSID
   #undef NEED_STRDUP
   #define HAVE_MMAP
  +#define USE_MMAP_FILES
   
   #define NO_TIMEZONE
   #include <stdio.h>
  
  
  
  1.112     +104 -13   apachen/src/core/http_core.c
  
  Index: http_core.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/core/http_core.c,v
  retrieving revision 1.111
  retrieving revision 1.112
  diff -u -r1.111 -r1.112
  --- http_core.c       1997/08/17 20:21:36     1.111
  +++ http_core.c       1997/08/18 07:19:34     1.112
  @@ -64,6 +64,28 @@
   #include "scoreboard.h"
   #include "fnmatch.h"
   
  +#ifdef USE_MMAP_FILES
  +#include <unistd.h>
  +#include <sys/mman.h>
  +
  +/* mmap support for static files based on ideas from John Heidemann's
  + * patch against 1.0.5.  See
  + * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
  + */
  +
  +/* Files have to be at least this big before they're mmap()d.  This is to
  + * deal with systems where the expense of doing an mmap() and an munmap()
  + * outweighs the benefit for small files.
  + */
  +#ifndef MMAP_THRESHOLD
  +#ifdef SUNOS4
  +#define MMAP_THRESHOLD               (8*1024)
  +#else
  +#define MMAP_THRESHOLD               0
  +#endif
  +#endif
  +#endif
  +
   /* Server core module... This module provides support for really basic
    * server operations, including options and commands which control the
    * operation of other modules.  Consider this the bureaucracy module.
  @@ -1500,6 +1522,20 @@
   
   int do_nothing (request_rec *r) { return OK; }
   
  +#ifdef USE_MMAP_FILES
  +struct mmap {
  +    void *mm;
  +    size_t length;
  +};
  +
  +static void mmap_cleanup (void *mmv)
  +{
  +    struct mmap *mmd = mmv;
  +
  +    munmap(mmd->mm, mmd->length);
  +}
  +#endif
  +
   /*
    * Default handler for MIME types without other handlers.  Only GET
    * and OPTIONS at this point... anyone who wants to write a generic
  @@ -1514,6 +1550,9 @@
         (core_dir_config *)get_module_config(r->per_dir_config, &core_module);
       int rangestatus, errstatus;
       FILE *f;
  +#ifdef USE_MMAP_FILES
  +    caddr_t mm;
  +#endif
   
       /* This handler has no use for a request body (yet), but we still
        * need to read and discard it if the client sent one.
  @@ -1555,24 +1594,76 @@
        || (errstatus = set_content_length (r, r->finfo.st_size)))
           return errstatus;
   
  -    if (d->content_md5 & 1) {
  -      table_set (r->headers_out, "Content-MD5", md5digest(r->pool, f));
  +#ifdef USE_MMAP_FILES
  +    block_alarms();
  +    if (r->finfo.st_size >= MMAP_THRESHOLD) {
  +     /* we need to protect ourselves in case we die while we've got the
  +      * file mmapped */
  +     mm = mmap (NULL, r->finfo.st_size, PROT_READ, MAP_PRIVATE,
  +                 fileno(f), 0);
  +    } else {
  +     mm = (caddr_t)-1;
       }
   
  -    rangestatus = set_byterange(r);
  -    send_http_header (r);
  -    
  -    if (!r->header_only) {
  -     if (!rangestatus)
  -         send_fd (f, r);
  -     else {
  -         long offset, length;
  -         while (each_byterange(r, &offset, &length)) {
  -             fseek(f, offset, SEEK_SET);
  -             send_fd_length(f, r, length);
  +    if (mm == (caddr_t)-1) {
  +     unblock_alarms();
  +
  +     log_unixerr ("mmap_handler", r->filename, "mmap failed", r->server);
  +#endif
  +
  +     if (d->content_md5 & 1) {
  +         table_set (r->headers_out, "Content-MD5", md5digest(r->pool, f));
  +     }
  +
  +     rangestatus = set_byterange(r);
  +     send_http_header (r);
  +     
  +     if (!r->header_only) {
  +         if (!rangestatus)
  +             send_fd (f, r);
  +         else {
  +             long offset, length;
  +             while (each_byterange(r, &offset, &length)) {
  +                 fseek(f, offset, SEEK_SET);
  +                 send_fd_length(f, r, length);
  +             }
  +         }
  +     }
  +
  +#ifdef USE_MMAP_FILES
  +    } else {
  +     struct mmap *mmd;
  +
  +     mmd = palloc (r->pool, sizeof (*mmd));
  +     mmd->mm = mm;
  +     mmd->length = r->finfo.st_size;
  +     register_cleanup (r->pool, (void *)mmd, mmap_cleanup, mmap_cleanup);
  +     unblock_alarms();
  +
  +     if (d->content_md5 & 1) {
  +         MD5_CTX context;
  +         
  +         MD5Init(&context);
  +         MD5Update(&context, (void *)mm, r->finfo.st_size);
  +         table_set (r->headers_out, "Content-MD5",
  +             md5contextTo64(r->pool, &context));
  +     }
  +
  +     rangestatus = set_byterange(r);
  +     send_http_header (r);
  +     
  +     if (!r->header_only) {
  +         if (!rangestatus)
  +             send_mmap (mm, r, 0, r->finfo.st_size);
  +         else {
  +             long offset, length;
  +             while (each_byterange(r, &offset, &length)) {
  +                 send_mmap(mm, r, offset, length);
  +             }
            }
        }
       }
  +#endif
   
       pfclose(r->pool, f);
       return OK;
  
  
  
  1.155     +62 -0     apachen/src/core/http_protocol.c
  
  Index: http_protocol.c
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/core/http_protocol.c,v
  retrieving revision 1.154
  retrieving revision 1.155
  diff -u -r1.154 -r1.155
  --- http_protocol.c   1997/08/18 07:17:26     1.154
  +++ http_protocol.c   1997/08/18 07:19:36     1.155
  @@ -1762,6 +1762,68 @@
       return total_bytes_sent;
   }
   
  +
  +
  +/* The code writes MMAP_SEGMENT_SIZE bytes at a time.  This is due to 
Apache's
  + * timeout model, which is a timeout per-write rather than a time for the
  + * entire transaction to complete.  Essentially this should be small enough
  + * so that in one Timeout period, your slowest clients should be reasonably
  + * able to receive this many bytes.
  + */
  +#ifndef MMAP_SEGMENT_SIZE
  +#define MMAP_SEGMENT_SIZE    32768
  +#endif
  +
  +/* send data from an in-memory buffer */
  +API_EXPORT(size_t) send_mmap(void * mm, request_rec *r, size_t offset,
  +    size_t length)
  +{
  +    size_t total_bytes_sent = 0;
  +    int n, w;
  +    
  +    if (length == 0) return 0;
  +
  +    soft_timeout("send mmap", r);
  +
  +    length += offset;
  +    while (!r->connection->aborted && offset < length) {
  +     if (length - offset > MMAP_SEGMENT_SIZE) {
  +         n = MMAP_SEGMENT_SIZE;
  +     } else {
  +         n = length - offset;
  +     }
  +
  +        while (n && !r->connection->aborted) {
  +            w = bwrite(r->connection->client, (char *)mm + offset, n);
  +            if (w > 0) {
  +                reset_timeout(r); /* reset timeout after successful write */
  +             total_bytes_sent += w;
  +                n -= w;
  +                offset += w;
  +            }
  +            else if (w < 0) {
  +                if (r->connection->aborted)
  +                    break;
  +                else if (errno == EAGAIN)
  +                    continue;
  +                else {
  +                    log_unixerr("send mmap lost connection to",
  +                                get_remote_host(r->connection,
  +                                    r->per_dir_config, REMOTE_NAME),
  +                                NULL, r->server);
  +                    bsetflag(r->connection->client, B_EOUT, 1);
  +                    r->connection->aborted = 1;
  +                    break;
  +                }
  +            }
  +        }
  +    }
  +    
  +    kill_timeout(r);
  +    SET_BYTES_SENT(r);
  +    return total_bytes_sent;
  +}
  +
   API_EXPORT(int) rputc (int c, request_rec *r)
   {
       if (r->connection->aborted) return EOF;
  
  
  
  1.26      +3 -0      apachen/src/core/http_protocol.h
  
  Index: http_protocol.h
  ===================================================================
  RCS file: /export/home/cvs/apachen/src/core/http_protocol.h,v
  retrieving revision 1.25
  retrieving revision 1.26
  diff -u -r1.25 -r1.26
  --- http_protocol.h   1997/07/24 04:23:59     1.25
  +++ http_protocol.h   1997/08/18 07:19:36     1.26
  @@ -113,6 +113,9 @@
   
   API_EXPORT(long) send_fb(BUFF *f, request_rec *r);
   API_EXPORT(long) send_fb_length(BUFF *f, request_rec *r, long length);
  +
  +API_EXPORT(size_t) send_mmap(void *mm, request_rec *r, size_t offset,
  +    size_t length);
        
   /* Hmmm... could macrofy these for now, and maybe forever, though the
    * definitions of the macros would get a whole lot hairier.
  
  
  

Reply via email to