You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ma...@hyperreal.org on 1998/07/09 21:46:00 UTC

cvs commit: apache-1.3/src/modules/proxy mod_proxy.c mod_proxy.h proxy_cache.c proxy_ftp.c proxy_http.c proxy_util.c

martin      98/07/09 12:45:59

  Modified:    htdocs/manual/mod directives.html mod_proxy.html
               src/modules/proxy mod_proxy.c mod_proxy.h proxy_cache.c
                        proxy_ftp.c proxy_http.c proxy_util.c
  Log:
  cache in the event that the client cancels the transfer, provided that
  the configured percentage of the file has already been transfered.
  It works for http transfers only.
  
  The new httpd.conf directive is:
  CacheForceCompletion <percentage>
  
  PR: 2277
  Submitted by: 	Glen Parker <gl...@nwlink.com>
  Reviewed by:	Martin Kraemer, Brian Behlendorf
  
  Revision  Changes    Path
  1.47      +1 -0      apache-1.3/htdocs/manual/mod/directives.html
  
  Index: directives.html
  ===================================================================
  RCS file: /home/cvs/apache-1.3/htdocs/manual/mod/directives.html,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -u -r1.46 -r1.47
  --- directives.html	1998/06/16 03:37:15	1.46
  +++ directives.html	1998/07/09 19:45:40	1.47
  @@ -71,6 +71,7 @@
   <LI><A HREF="mod_proxy.html#cachedefaultexpire">CacheDefaultExpire</A>
   <LI><A HREF="mod_proxy.html#cachedirlength">CacheDirLength</A>
   <LI><A HREF="mod_proxy.html#cachedirlevels">CacheDirLevels</A>
  +<LI><A HREF="mod_proxy.html#cacheforcecompletion">CacheForceCompletion</A>
   <LI><A HREF="mod_proxy.html#cachegcinterval">CacheGcInterval</A>
   <LI><A HREF="mod_proxy.html#cachelastmodifiedfactor">CacheLastModifiedFactor</A>
   <LI><A HREF="mod_proxy.html#cachemaxexpire">CacheMaxExpire</A>
  
  
  
  1.41      +42 -0     apache-1.3/htdocs/manual/mod/mod_proxy.html
  
  Index: mod_proxy.html
  ===================================================================
  RCS file: /home/cvs/apache-1.3/htdocs/manual/mod/mod_proxy.html,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -u -r1.40 -r1.41
  --- mod_proxy.html	1998/06/16 02:11:31	1.40
  +++ mod_proxy.html	1998/07/09 19:45:40	1.41
  @@ -56,6 +56,7 @@
   <LI><A HREF="#cachegcinterval">CacheGcInterval</A>
   <LI><A HREF="#cachedirlevels">CacheDirLevels</A>
   <LI><A HREF="#cachedirlength">CacheDirLength</A>
  +<LI><A HREF="#cacheforcecompletion">CacheForceCompletion</A>
   <LI><A HREF="#nocache">NoCache</A>
   </UL>
   
  @@ -548,6 +549,47 @@
     NoProxy         .mycompany.com 192.168.112.0/21 
     ProxyDomain     .mycompany.com
   </PRE>
  +
  +<HR>
  +
  +<H2><A NAME="cacheforcecompletion">CacheForceCompletion</A></H2>
  +<A
  + HREF="directive-dict.html#Syntax"
  + REL="Help"
  +><STRONG>Syntax:</STRONG></A> CacheForceCompletion <EM><percentage></EM><BR>
  +<A
  + HREF="directive-dict.html#Default"
  + REL="Help"
  +><STRONG>Default:</STRONG></A> <EM>90</EM><BR>
  +<A
  + HREF="directive-dict.html#Context"
  + REL="Help"
  +><STRONG>Context:</STRONG></A> server config, virtual host<BR>
  +<A
  + HREF="directive-dict.html#Override"
  + REL="Help"
  +><STRONG>Override:</STRONG></A> <EM>Not applicable</EM><BR>
  +<A
  + HREF="directive-dict.html#Status"
  + REL="Help"
  +><STRONG>Status:</STRONG></A> Base<BR>
  +<A
  + HREF="directive-dict.html#Module"
  + REL="Help"
  +><STRONG>Module:</STRONG></A> mod_proxy<BR>
  +<A
  + HREF="directive-dict.html#Compatibility"
  + REL="Help"
  +><STRONG>Compatibility:</STRONG></A> CacheForceCompletion is only available in
  +Apache 1.3 and later.<P>
  +
  +If an http transfer that is being cached is cancelled, the proxy module will
  +complete the transfer to cache if more than the percentage specified has
  +already been transferred.<P>
  +
  +This is a percentage, and must be a number between 1 and 100, or 0 to use
  +the default.  100 will cause a document to be cached only if the transfer
  +was allowed to complete.  A number between 60 and 90 is recommended.
   
   <HR>
   
  
  
  
  1.55      +19 -0     apache-1.3/src/modules/proxy/mod_proxy.c
  
  Index: mod_proxy.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/mod_proxy.c,v
  retrieving revision 1.54
  retrieving revision 1.55
  diff -u -u -r1.54 -r1.55
  --- mod_proxy.c	1998/06/13 15:22:58	1.54
  +++ mod_proxy.c	1998/07/09 19:45:55	1.55
  @@ -405,6 +405,7 @@
       /* at these levels, the cache can have 2^18 directories (256,000)  */
       ps->cache.dirlevels = 3;
       ps->cache.dirlength = 1;
  +    ps->cache.cache_completion = DEFAULT_CACHE_COMPLETION;
   
       return ps;
   }
  @@ -742,6 +743,22 @@
       return NULL;
   }
   
  +static const char*
  +    set_cache_completion(cmd_parms *parms, void *dummy, char *arg)
  +{
  +    proxy_server_conf *psf =
  +    ap_get_module_config(parms->server->module_config, &proxy_module);
  +    int s = atoi(arg);
  +    if (s > 100 || s < 0) {
  +	return "CacheForceCompletion must be <= 100 percent, "
  +               "or 0 for system default.";
  +    }
  +
  +    if (s > 0)
  +      psf->cache.cache_completion = ((float)s / 100);
  +    return NULL;    
  +}
  +
   static const handler_rec proxy_handlers[] =
   {
       {"proxy-server", proxy_handler},
  @@ -784,6 +801,8 @@
        "The number of characters in subdirectory names"},
       {"NoCache", set_cache_exclude, NULL, RSRC_CONF, ITERATE,
        "A list of names, hosts or domains for which caching is *not* provided"},
  +    {"CacheForceCompletion", set_cache_completion, NULL, RSRC_CONF, TAKE1,
  +     "Force a http cache completion after this percentage is loaded"},
       {NULL}
   };
   
  
  
  
  1.37      +4 -0      apache-1.3/src/modules/proxy/mod_proxy.h
  
  Index: mod_proxy.h
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/mod_proxy.h,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -u -r1.36 -r1.37
  --- mod_proxy.h	1998/06/13 15:22:59	1.36
  +++ mod_proxy.h	1998/07/09 19:45:56	1.37
  @@ -184,6 +184,7 @@
   #define DEFAULT_CACHE_MAXEXPIRE SEC_ONE_DAY
   #define DEFAULT_CACHE_EXPIRE    SEC_ONE_HR
   #define DEFAULT_CACHE_LMFACTOR (0.1)
  +#define DEFAULT_CACHE_COMPLETION (0.9)
   
   /* static information about the local cache */
   struct cache_conf {
  @@ -195,6 +196,7 @@
       time_t gcinterval;		/* garbage collection interval, in seconds */
       int dirlevels;		/* Number of levels of subdirectories */
       int dirlength;		/* Length of subdirectory names */
  +    float cache_completion;	/* Force cache completion after this point */
   };
   
   typedef struct {
  @@ -232,6 +234,8 @@
       off_t len;			/* content length */
       char *protocol;		/* Protocol, and major/minor number, e.g. HTTP/1.1 */
       int status;			/* the status of the cached file */
  +    unsigned int written;	/* total *content* bytes written to cache */
  +    float cache_completion;	/* specific to this request */
       char *resp_line;		/* the whole status like (protocol, code + message) */
       array_header *hdrs;		/* the HTTP headers of the file */
   };
  
  
  
  1.46      +9 -1      apache-1.3/src/modules/proxy/proxy_cache.c
  
  Index: proxy_cache.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_cache.c,v
  retrieving revision 1.45
  retrieving revision 1.46
  diff -u -u -r1.45 -r1.46
  --- proxy_cache.c	1998/07/09 09:52:20	1.45
  +++ proxy_cache.c	1998/07/09 19:45:56	1.46
  @@ -693,8 +693,11 @@
   	    cachefp = NULL;
   	}
       }
  +/* fixed?  in this case, we want to get the headers from the remote server
  +   it will be handled later if we don't do this (I hope ;-)
       if (cachefp == NULL)
   	c->hdrs = ap_make_array(r->pool, 2, sizeof(struct hdr_entry));
  +*/
       /* FIXME: Shouldn't we check the URL somewhere? */
       now = time(NULL);
   /* Ok, have we got some un-expired data? */
  @@ -1034,7 +1037,10 @@
       if (c->fp == NULL)
   	return;
   
  +/* don't care how much was sent, but rather how much was written to cache
       ap_bgetopt(c->req->connection->client, BO_BYTECT, &bc);
  + */
  +    bc = c->written;
   
       if (c->len != -1) {
   /* file lengths don't match; don't cache it */
  @@ -1044,11 +1050,13 @@
   	    return;
   	}
       }
  +/* don't care if aborted, cache it if fully retrieved from host!
       else if (c->req->connection->aborted) {
  -	ap_pclosef(c->req->pool, c->fp->fd);	/* no need to flush */
  +	ap_pclosef(c->req->pool, c->fp->fd);	/ no need to flush /
   	unlink(c->tempfile);
   	return;
       }
  +*/
       else {
   /* update content-length of file */
   	char buff[9];
  
  
  
  1.64      +9 -2      apache-1.3/src/modules/proxy/proxy_ftp.c
  
  Index: proxy_ftp.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_ftp.c,v
  retrieving revision 1.63
  retrieving revision 1.64
  diff -u -u -r1.63 -r1.64
  --- proxy_ftp.c	1998/07/08 17:47:09	1.63
  +++ proxy_ftp.c	1998/07/09 19:45:56	1.64
  @@ -1003,6 +1003,8 @@
       r->status_line = "200 OK";
   
       resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry));
  +    c->hdrs = resp_hdrs;
  +
       if (parms[0] == 'd')
   	ap_proxy_add_header(resp_hdrs, "Content-Type", "text/html", HDR_REP);
       else {
  @@ -1034,8 +1036,11 @@
   	ap_bclose(f);
   	return i;
       }
  +
       cache = c->fp;
   
  +    c->hdrs = resp_hdrs;
  +
       if (!pasvmode) {		/* wait for connection */
   	ap_hard_timeout("proxy ftp data connect", r);
   	clen = sizeof(struct sockaddr_in);
  @@ -1100,9 +1105,11 @@
       r->sent_bodyct = 1;
   /* send body */
       if (!r->header_only) {
  -	if (parms[0] != 'd')
  +	if (parms[0] != 'd') {
  +/* we need to set this for ap_proxy_send_fb()... */
  +	    c->cache_completion = 0;
   	    ap_proxy_send_fb(data, r, cache, c);
  -	else
  +	} else
   	    send_dir(data, r, cache, c, url);
   
   	if (rc == 125 || rc == 150)
  
  
  
  1.53      +6 -1      apache-1.3/src/modules/proxy/proxy_http.c
  
  Index: proxy_http.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_http.c,v
  retrieving revision 1.52
  retrieving revision 1.53
  diff -u -u -r1.52 -r1.53
  --- proxy_http.c	1998/07/08 17:47:10	1.52
  +++ proxy_http.c	1998/07/09 19:45:56	1.53
  @@ -371,6 +371,8 @@
   	resp_hdrs = ap_make_array(p, 2, sizeof(struct hdr_entry));
       }
   
  +    c->hdrs = resp_hdrs;
  +
       ap_kill_timeout(r);
   
   /*
  @@ -459,8 +461,11 @@
   /* send body */
   /* if header only, then cache will be NULL */
   /* HTTP/1.0 tells us to read to EOF, rather than content-length bytes */
  -    if (!r->header_only)
  +    if (!r->header_only) {
  +/* we need to set this for ap_proxy_send_fb()... */
  +	c->cache_completion = conf->cache.cache_completion;
   	ap_proxy_send_fb(f, r, cache, c);
  +    }
   
       ap_proxy_cache_tidy(c);
   
  
  
  
  1.65      +85 -25    apache-1.3/src/modules/proxy/proxy_util.c
  
  Index: proxy_util.c
  ===================================================================
  RCS file: /home/cvs/apache-1.3/src/modules/proxy/proxy_util.c,v
  retrieving revision 1.64
  retrieving revision 1.65
  diff -u -u -r1.64 -r1.65
  --- proxy_util.c	1998/07/08 17:47:10	1.64
  +++ proxy_util.c	1998/07/09 19:45:57	1.65
  @@ -443,12 +443,16 @@
   
   long int ap_proxy_send_fb(BUFF *f, request_rec *r, BUFF *f2, struct cache_req *c)
   {
  +    int  ok = 1;
       char buf[IOBUFSIZE];
  -    long total_bytes_sent;
  +    long total_bytes_rcv;
       register int n, o, w;
       conn_rec *con = r->connection;
  +    int alt_to = 1;
   
  -    total_bytes_sent = 0;
  +    total_bytes_rcv = 0;
  +    if (c)
  +        c->written = 0;
   
   #ifdef CHARSET_EBCDIC
       /* The cache copy is ASCII, not EBCDIC, even for text/html) */
  @@ -462,10 +466,43 @@
        * it is unsafe to do a soft_timeout here, at least until the proxy
        * has its own timeout handler which can set both buffers to EOUT.
        */
  +
  +    ap_kill_timeout(r);
  +
  +#ifdef WIN32
  +    /* works fine under win32, so leave it */
       ap_hard_timeout("proxy send body", r);
  +    alt_to = 0;
  +#else
  +    /* CHECKME! Since hard_timeout won't work in unix on sends with partial
  +     * cache completion, we have to alternate between hard_timeout
  +     * for reads, and soft_timeout for send.  This is because we need
  +     * to get a return from ap_bwrite to be able to continue caching.
  +     * BUT, if we *can't* continue anyway, just use hard_timeout.
  +     */
  +
  +    if (c) {
  +        if (c->len <= 0 || c->cache_completion == 1) {
  +            ap_hard_timeout("proxy send body", r);
  +            alt_to = 0;
  +        }
  +    } else {
  +        ap_hard_timeout("proxy send body", r);
  +        alt_to = 0;
  +    }
  +#endif
   
  -    while (!con->aborted && f != NULL) {
  +    while (ok && f != NULL) {
  +        if (alt_to)
  +            ap_hard_timeout("proxy send body", r);
  +
   	n = ap_bread(f, buf, IOBUFSIZE);
  +
  +        if (alt_to)
  +            ap_kill_timeout(r);
  +        else
  +            ap_reset_timeout(r);
  +
   	if (n == -1) {		/* input error */
   	    if (f2 != NULL)
   		f2 = ap_proxy_cache_error(c);
  @@ -474,34 +511,57 @@
   	if (n == 0)
   	    break;		/* EOF */
   	o = 0;
  -	total_bytes_sent += n;
  +	total_bytes_rcv += n;
   
  -	if (f2 != NULL)
  -	    if (ap_bwrite(f2, buf, n) != n)
  -		f2 = ap_proxy_cache_error(c);
  -
  -	while (n && !con->aborted) {
  -	    w = ap_bwrite(con->client, &buf[o], n);
  -	    if (w <= 0) {
  -		if (f2 != NULL) {
  -		    ap_pclosef(c->req->pool, c->fp->fd);
  -		    c->fp = NULL;
  -		    f2 = NULL;
  -		    con->aborted = 1;
  -		    unlink(c->tempfile);
  -		}
  -		break;
  -	    }
  -	    ap_reset_timeout(r);	/* reset timeout after successful write */
  -	    n -= w;
  -	    o += w;
  -	}
  +        if (f2 != NULL) {
  +            if (ap_bwrite(f2, &buf[0], n) != n) {
  +                f2 = ap_proxy_cache_error(c);
  +            } else {
  +                c->written += n;
  +            }
  +        }
  +
  +        while (n && !con->aborted) {
  +            if (alt_to)
  +                ap_soft_timeout("proxy send body", r);
  +
  +            w = ap_bwrite(con->client, &buf[o], n);
  +
  +            if (alt_to)
  +                ap_kill_timeout(r);
  +            else
  +                ap_reset_timeout(r);
  +
  +            if (w <= 0) {
  +                if (f2 != NULL) {
  +                    /* when a send failure occurs, we need to decide
  +                     * whether to continue loading and caching the
  +                     * document, or to abort the whole thing
  +                     */
  +                    ok = (c->len > 0) &&
  +                         (c->cache_completion > 0) &&
  +                         (c->len * c->cache_completion < total_bytes_rcv);
  +
  +                    if (! ok) {
  +                        ap_pclosef(c->req->pool, c->fp->fd);
  +                        c->fp = NULL;
  +                        f2 = NULL;
  +                        unlink(c->tempfile);
  +                    }
  +                }
  +                con->aborted = 1;
  +                break;
  +            }
  +            n -= w;
  +            o += w;
  +        }
       }
  +
       if (!con->aborted)
   	ap_bflush(con->client);
   
       ap_kill_timeout(r);
  -    return total_bytes_sent;
  +    return total_bytes_rcv;
   }
   
   /*