You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ia...@apache.org on 2002/01/25 21:09:34 UTC

cvs commit: httpd-2.0/modules/experimental cache_storage.c cache_util.c mod_cache.c mod_cache.h mod_mem_cache.c

ianh        02/01/25 12:09:34

  Modified:    modules/experimental cache_storage.c cache_util.c
                        mod_cache.c mod_cache.h mod_mem_cache.c
  Log:
  I haven't created the optional function to specify the cache_key yet,
  That will come after this patch.
  
  ok.. brief summary of whats changed
  
  * new Optional Directives
  	* CacheMemEntrySize -- max size of a individual entry in memory
  		cache
  	* CacheIgnoreNoLastMod - so we can cache mod-included files
  
  * it tries to figure out the size of the request based on buckets if the
  	content-length header isn't set
  
  * mem_cache now caches the subprocess_env & notes tables
  * the CACHE_IN/OUT/CONDITIONAL run at FTYPE_CONTENT+1, so that
  	all other content filters run BEFORE the cache in.
  
  note: the code is still experimental, and we need a bit more work
  mainly...
  * garbage collection
  * cache stats/reporting
  * manual removal of a key.
  
  Revision  Changes    Path
  1.11      +31 -45    httpd-2.0/modules/experimental/cache_storage.c
  
  Index: cache_storage.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/experimental/cache_storage.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- cache_storage.c	10 Jan 2002 09:11:32 -0000	1.10
  +++ cache_storage.c	25 Jan 2002 20:09:33 -0000	1.11
  @@ -78,11 +78,14 @@
   {
       const char *next = types;
       const char *type;
  +    const char *key;
  +
  +    key = cache_create_key(r);
   
       /* for each specified cache type, delete the URL */
       while(next) {
           type = ap_cache_tokstr(r->pool, next, &next);
  -        cache_run_remove_url(type, url);
  +        cache_run_remove_url(type, key);
       }
       return OK;
   }
  @@ -104,14 +107,16 @@
       cache_handle_t *h = apr_pcalloc(r->pool, sizeof(h));
       const char *next = types;
       const char *type;
  +    const char *key;
       apr_status_t rv;
  -    cache_request_rec *cache = (cache_request_rec *) ap_get_module_config(r->request_config, 
  -                                                                          &cache_module);
  +    cache_request_rec *cache = (cache_request_rec *) 
  +                         ap_get_module_config(r->request_config, &cache_module);
   
       /* for each specified cache type, delete the URL */
  +    key = cache_create_key(r);
       while (next) {
           type = ap_cache_tokstr(r->pool, next, &next);
  -        switch (rv = cache_run_create_entity(h, type, url, size)) {
  +        switch (rv = cache_run_create_entity(h, type, key, size)) {
           case OK: {
               cache->handle = h;
               return OK;
  @@ -157,15 +162,16 @@
       const char *type;
       apr_status_t rv;
       cache_info *info;
  -    cache_request_rec *cache = (cache_request_rec *) ap_get_module_config(r->request_config, 
  -                                                                          &cache_module);
  -
  +    const char *key;
  +    cache_request_rec *cache = (cache_request_rec *) 
  +                         ap_get_module_config(r->request_config, &cache_module);
  +    key = cache_create_key(r);
       /* go through the cache types till we get a match */
       cache->handle = apr_palloc(r->pool, sizeof(cache_handle_t));
   
       while (next) {
           type = ap_cache_tokstr(r->pool, next, &next);
  -        switch ((rv = cache_run_open_entity(cache->handle, type, url))) {
  +        switch ((rv = cache_run_open_entity(cache->handle, type, key))) {
           case OK: {
               info = &(cache->handle->cache_obj->info);
               /* XXX:
  @@ -196,10 +202,11 @@
       return DECLINED;
   }
   
  -apr_status_t cache_write_entity_headers(cache_handle_t *h, request_rec *r, cache_info *info,
  -                                        apr_table_t *headers)
  +apr_status_t cache_write_entity_headers(cache_handle_t *h, 
  +                                        request_rec *r, 
  +                                        cache_info *info)
   {
  -    h->write_headers(h, r, info, headers);
  +    h->write_headers(h, r, info);
       return APR_SUCCESS;
   }
   apr_status_t cache_write_entity_body(cache_handle_t *h, apr_bucket_brigade *b) 
  @@ -210,17 +217,15 @@
       return rv;
   }
   
  -apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r, 
  -                                       apr_table_t **headers)
  +apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r)
   {
       cache_info *info = &(h->cache_obj->info);
   
       /* Build the header table from info in the info struct */
  -    *headers = apr_table_make(r->pool, 15);
  -
  -    h->read_headers(h, r, *headers);
  +    h->read_headers(h, r);
   
       r->content_type = apr_pstrdup(r->pool, info->content_type);
  +    r->filename = apr_pstrdup(r->pool, info->filename );
   
       return APR_SUCCESS;
   }
  @@ -230,37 +235,18 @@
       return APR_SUCCESS;
   }
   
  +const char* cache_create_key( request_rec *r ) 
  +{
  +    return r->uri;
  +}
   APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, create_entity, 
                                         (cache_handle_t *h, const char *type, 
  -                                      char *url, apr_size_t len),(h,type,url,len),DECLINED)
  +                                      const char *urlkey, apr_size_t len),
  +                                      (h,type,urlkey,len),DECLINED)
   APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, open_entity,  
                                         (cache_handle_t *h, const char *type, 
  -                                      char *url),(h,type,url),DECLINED)
  +                                      const char *urlkey),(h,type,urlkey),
  +                                      DECLINED)
   APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(cache, CACHE, int, remove_url, 
  -                                    (const char *type, char *url),(type,url),OK,DECLINED)
  -#if 0
  -/* BillS doesn't think these should be hooks.
  - * All functions which accept a cache_handle * argument should use
  - * function pointers in the cache_handle. Leave them here for now as 
  - * points for discussion...
  - */
  -
  -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, remove_entity, 
  -                                     (cache_handle *h),(h),DECLINED)
  -
  -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, read_entity_headers, 
  -                                     (cache_handle *h, request_rec *r,
  -                                      apr_table_t **headers),
  -                                      (h,info,headers_in,headers_out),DECLINED)
  -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, read_entity_body, 
  -                                     (cache_handle *h,
  -                                      apr_bucket_brigade *out),(h,out),DECLINED)
  -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, write_entity_headers, 
  -                                     (cache_handle *h, cache_info *info,
  -                                      apr_table_t *headers_in, 
  -                                      apr_table_t *headers_out),
  -                                      (h,info,headers_in,headers_out),DECLINED)
  -APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(cache, CACHE, int, write_entity_body, 
  -                                     (cache_handle *h,
  -                                      apr_bucket_brigade *in),(h,in),DECLINED)
  -#endif
  +                                    (const char *type, const char *urlkey),
  +                                    (type,urlkey),OK,DECLINED)
  
  
  
  1.5       +60 -55    httpd-2.0/modules/experimental/cache_util.c
  
  Index: cache_util.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/experimental/cache_util.c,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- cache_util.c	24 Aug 2001 16:57:13 -0000	1.4
  +++ cache_util.c	25 Jan 2002 20:09:33 -0000	1.5
  @@ -72,7 +72,7 @@
           apr_table_get(r->headers_in, "If-Modified-Since") ||
           apr_table_get(r->headers_in, "If-Unmodified-Since")) {
   
  -	return 1;
  +        return 1;
       }
       return 0;
   }
  @@ -97,33 +97,37 @@
       }
   }
   
  -const char *ap_cache_get_cachetype(request_rec *r, cache_server_conf *conf, const char *url)
  +const char *ap_cache_get_cachetype(request_rec *r, 
  +                                   cache_server_conf *conf, 
  +                                   const char *url)
   {
       const char *type = NULL;
       int i;
   
       /* loop through all the cacheenable entries */
       for (i = 0; i < conf->cacheenable->nelts; i++) {
  -	struct cache_enable *ent = (struct cache_enable *) conf->cacheenable->elts;
  -	const char *thisurl = ent[i].url;
  -	const char *thistype = ent[i].type;
  -	if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
  -	    if (!type) {
  -		type = thistype;
  -	    }
  -	    else {
  -		type = apr_pstrcat(r->pool, type, ",", thistype, NULL);
  -	    }
  -	}
  +        struct cache_enable *ent = 
  +                                (struct cache_enable *)conf->cacheenable->elts;
  +        const char *thisurl = ent[i].url;
  +        const char *thistype = ent[i].type;
  +        if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
  +            if (!type) {
  +                type = thistype;
  +            }
  +            else {
  +                type = apr_pstrcat(r->pool, type, ",", thistype, NULL);
  +            }
  +        }
       }
   
       /* then loop through all the cachedisable entries */
       for (i = 0; i < conf->cachedisable->nelts; i++) {
  -	struct cache_disable *ent = (struct cache_disable *) conf->cachedisable->elts;
  -	const char *thisurl = ent[i].url;
  -	if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
  -	    type = NULL;
  -	}
  +        struct cache_disable *ent = 
  +                               (struct cache_disable *)conf->cachedisable->elts;
  +        const char *thisurl = ent[i].url;
  +        if ((thisurl) && !strncasecmp(thisurl, url, strlen(thisurl))) {
  +            type = NULL;
  +        }
       }
   
       return type;
  @@ -145,35 +149,35 @@
       len = strlen(key);
   
       while (list != NULL) {
  -	p = strchr((char *) list, ',');
  -	if (p != NULL) {
  -	    i = p - list;
  -	    do
  -		p++;
  -	    while (ap_isspace(*p));
  -	}
  -	else
  -	    i = strlen(list);
  -
  -	while (i > 0 && ap_isspace(list[i - 1]))
  -	    i--;
  -	if (i == len && strncasecmp(list, key, len) == 0) {
  -	    if (val) {
  -		p = strchr((char *) list, ',');
  -		while (ap_isspace(*list)) {
  -		    list++;
  -		}
  -		if ('=' == list[0])
  -		    list++;
  -		while (ap_isspace(*list)) {
  -		    list++;
  -		}
  -		strncpy(valbuf, list, MIN(p-list, sizeof(valbuf)-1));
  -		*val = valbuf;
  -	    }
  -	    return 1;
  -	}
  -	list = p;
  +        p = strchr((char *) list, ',');
  +        if (p != NULL) {
  +            i = p - list;
  +            do
  +            p++;
  +            while (ap_isspace(*p));
  +        }
  +        else
  +            i = strlen(list);
  +
  +        while (i > 0 && ap_isspace(list[i - 1]))
  +            i--;
  +        if (i == len && strncasecmp(list, key, len) == 0) {
  +            if (val) {
  +            p = strchr((char *) list, ',');
  +            while (ap_isspace(*list)) {
  +                list++;
  +            }
  +            if ('=' == list[0])
  +                list++;
  +            while (ap_isspace(*list)) {
  +                list++;
  +            }
  +            strncpy(valbuf, list, MIN(p-list, sizeof(valbuf)-1));
  +            *val = valbuf;
  +            }
  +            return 1;
  +        }
  +        list = p;
       }
       return 0;
   }
  @@ -186,21 +190,22 @@
   
       s = ap_strchr_c(list, ',');
       if (s != NULL) {
  -	i = s - list;
  -	do
  -	    s++;
  -	while (apr_isspace(*s));
  +        i = s - list;
  +        do
  +            s++;
  +        while (apr_isspace(*s))
  +            ; /* noop */
       }
       else
  -	i = strlen(list);
  +        i = strlen(list);
   
       while (i > 0 && apr_isspace(list[i - 1]))
  -	i--;
  +        i--;
   
       *str = s;
       if (i)
  -	return apr_pstrndup(p, list, i);
  +        return apr_pstrndup(p, list, i);
       else
  -	return NULL;
  +        return NULL;
   
   }
  
  
  
  1.19      +159 -65   httpd-2.0/modules/experimental/mod_cache.c
  
  Index: mod_cache.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_cache.c,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- mod_cache.c	4 Jan 2002 17:58:36 -0000	1.18
  +++ mod_cache.c	25 Jan 2002 20:09:33 -0000	1.19
  @@ -83,8 +83,6 @@
    *     oh well.
    */
   
  -int ap_url_cache_handler(request_rec *r);
  -
   int ap_url_cache_handler(request_rec *r)
   {
       apr_status_t rv;
  @@ -95,8 +93,9 @@
       const char *types;
       cache_info *info = NULL;
       cache_request_rec *cache;
  -    cache_server_conf *conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, 
  -                                                                         &cache_module);
  +    cache_server_conf *conf = 
  +        (cache_server_conf *) ap_get_module_config(r->server->module_config, 
  +                                                   &cache_module);
   
       /* we don't handle anything but GET */
       if (r->method_number != M_GET) return DECLINED;
  @@ -111,7 +110,8 @@
                    "cache: URL %s is being handled by %s", path, types);
   
       /* make space for the per request config */
  -    cache = (cache_request_rec *) ap_get_module_config(r->request_config, &cache_module);
  +    cache = (cache_request_rec *) ap_get_module_config(r->request_config, 
  +                                                       &cache_module);
       if (!cache) {
           cache = ap_pcalloc(r->pool, sizeof(cache_request_rec));
           ap_set_module_config(r->request_config, &cache_module, cache);
  @@ -182,7 +182,8 @@
   
               /* fresh data available */
               ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                         "cache: fresh cache - add cache_out filter and handle request");
  +                         "cache: fresh cache - add cache_out filter and "
  +                         "handle request");
   
               /* We are in the quick handler hook, which means that no output
                * filters have been set. So lets run the insert_filter hook.
  @@ -203,7 +204,9 @@
               out = apr_brigade_create(r->pool);
               if (APR_SUCCESS != (rv = ap_pass_brigade(r->output_filters, out))) {
                   ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
  -                             "cache: error returned while trying to return %s cached data", cache->type);
  +                             "cache: error returned while trying to return %s "
  +                             "cached data", 
  +                             cache->type);
                   return rv;
               }
               return OK;
  @@ -214,8 +217,10 @@
                            "cache: stale cache - test conditional");
               /* if conditional request */
               if (ap_cache_request_is_conditional(r)) {
  -                ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                             "cache: conditional - add cache_in filter and DECLINE");
  +                ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                             r->server,
  +                             "cache: conditional - add cache_in filter and "
  +                             "DECLINE");
                   /* add cache_in filter */
                   ap_add_output_filter("CACHE_IN", NULL, r, r->connection);
                   /* return DECLINED */
  @@ -225,30 +230,43 @@
               else {
                   /* fudge response into a conditional */
                   if (info && info->etag) {
  -                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                                 "cache: nonconditional - fudge conditional by etag");
  +                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                                 r->server,
  +                                 "cache: nonconditional - fudge conditional "
  +                                 "by etag");
                       /* if we have a cached etag */
                       apr_table_set(r->headers_in, "If-None-Match", info->etag);
                   }
                   else if (info && info->lastmods) {
  -                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                                 "cache: nonconditional - fudge conditional by lastmod");
  +                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                                 r->server,
  +                                 "cache: nonconditional - fudge conditional "
  +                                 "by lastmod");
                       /* if we have a cached IMS */
  -                    apr_table_set(r->headers_in, "If-Modified-Since", info->lastmods);
  +                    apr_table_set(r->headers_in, 
  +                                  "If-Modified-Since", 
  +                                  info->lastmods);
                   }
                   else {
                       /* something else - pretend there was no cache */
  -                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                                 "cache: nonconditional - no cached etag/lastmods - add cache_in and DECLINE");
  +                    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                                 r->server,
  +                                 "cache: nonconditional - no cached "
  +                                 "etag/lastmods - add cache_in and DECLINE");
                       /* add cache_in filter to cache this request */
                       ap_add_output_filter("CACHE_IN", NULL, r, r->connection);
                       /* return DECLINED */
                       return DECLINED;
                   }
                   /* add cache_conditional filter */
  -                ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                             "cache: nonconditional - add cache_conditional and DECLINE");
  -                ap_add_output_filter("CACHE_CONDITIONAL", NULL, r, r->connection);
  +                ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                             r->server,
  +                             "cache: nonconditional - add cache_conditional and"
  +                             " DECLINE");
  +                ap_add_output_filter("CACHE_CONDITIONAL", 
  +                                     NULL, 
  +                                     r, 
  +                                     r->connection);
                   /* return DECLINED */
                   return DECLINED;
               }
  @@ -256,8 +274,11 @@
       }
       else {
           /* error */
  -        ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
  -                     "cache: error returned while checking for cached file by %s cache", cache->type);
  +        ap_log_error(APLOG_MARK, APLOG_ERR, rv, 
  +                     r->server,
  +                     "cache: error returned while checking for cached file by "
  +                     "%s cache", 
  +                     cache->type);
           return DECLINED;
       }
   }
  @@ -268,14 +289,12 @@
    *
    * Deliver cached content (headers and body) up the stack.
    */
  -int ap_cache_out_filter(ap_filter_t *f, apr_bucket_brigade *bb);
  -
   int ap_cache_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
   {
       request_rec *r = f->r;
  -    apr_table_t *headers;
  -    cache_request_rec *cache = (cache_request_rec *) ap_get_module_config(r->request_config, 
  -                                                                          &cache_module);
  +    cache_request_rec *cache = 
  +        (cache_request_rec *) ap_get_module_config(r->request_config, 
  +                                                   &cache_module);
   
       if (!cache) {
           /* user likely configured CACHE_OUT manually; they should use mod_cache
  @@ -287,10 +306,9 @@
       }
   
       ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -		 "cache: running CACHE_OUT filter");
  +            "cache: running CACHE_OUT filter");
   
  -    cache_read_entity_headers(cache->handle, r, &headers);
  -    r->headers_out = headers;
  +    cache_read_entity_headers(cache->handle, r);    
       cache_read_entity_body(cache->handle, bb);
   
       /* This filter is done once it has served up its content */
  @@ -310,7 +328,6 @@
    * Otherwise
    *   replace ourselves with cache_in filter
    */
  -int ap_cache_conditional_filter(ap_filter_t *f, apr_bucket_brigade *in);
   
   int ap_cache_conditional_filter(ap_filter_t *f, apr_bucket_brigade *in)
   {
  @@ -343,7 +360,6 @@
    *   pass the data to the next filter (the network)
    *
    */
  -int ap_cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in);
   
   int ap_cache_in_filter(ap_filter_t *f, apr_bucket_brigade *in)
   {
  @@ -387,7 +403,9 @@
        * if the setup section (see below) is complete.
        */
   
  -    /* have we already run the cachability check and set up the cached file handle? */
  +    /* have we already run the cachability check and set up the cached file 
  +     * handle? 
  +     */
       if(cache->in_checked) {
           /* pass the brigades into the cache, then pass them
            * up the filter stack
  @@ -447,7 +465,8 @@
        * telling us to serve the cached copy. */
       if ((r->status != HTTP_OK && r->status != HTTP_NON_AUTHORITATIVE && 
            r->status != HTTP_MULTIPLE_CHOICES && 
  -         r->status != HTTP_MOVED_PERMANENTLY && r->status != HTTP_NOT_MODIFIED) ||
  +         r->status != HTTP_MOVED_PERMANENTLY && 
  +         r->status != HTTP_NOT_MODIFIED) ||
   
       /* if a broken Expires header is present, don't cache it */
           (exps != NULL && exp == APR_DATE_BAD) ||
  @@ -456,8 +475,13 @@
        * this untouched to the user agent, it's not for us. */
           (r->status == HTTP_NOT_MODIFIED && (NULL == cache->handle)) ||
   
  -    /* 200 OK response from HTTP/1.0 and up without a Last-Modified header/Etag */
  -        (r->status == HTTP_OK && lastmods == NULL && etag == NULL) ||
  +    /* 200 OK response from HTTP/1.0 and up without a Last-Modified header/Etag 
  +     */
  +    /* XXX mod-include clears last_modified/expires/etags - this is why we have
  +     * a optional function for a key-gen ;-) 
  +     */
  +        (r->status == HTTP_OK && lastmods == NULL && etag == NULL 
  +            && (conf->no_last_mod_ignore ==0)) ||
   
       /* HEAD requests */
           r->header_only ||
  @@ -515,8 +539,29 @@
           if (cl) {
               size = atol(cl);
           }
  -        else
  -            size = -1;
  +        else {
  +
  +            /* if we don't get the content-length, see if we have all the 
  +             * buckets and use their length to calculate the size 
  +             */
  +            apr_bucket *e;
  +            int all_buckets_here=0;
  +            size=0;
  +            APR_BRIGADE_FOREACH(e, in) {
  +                if (APR_BUCKET_IS_EOS(e)) {
  +                    all_buckets_here=1;
  +                    break;
  +                }
  +                if (APR_BUCKET_IS_FLUSH(e)) {
  +                    continue;
  +                }
  +                size += e->length;
  +            }
  +
  +            if (!all_buckets_here) {
  +                size = -1;
  +            }
  +        }
       }
   
       /* It's safe to cache the response.
  @@ -579,10 +624,12 @@
           info->date = APR_DATE_BAD;
   
       now = apr_time_now();
  -    if (info->date == APR_DATE_BAD) {	/* No, or bad date */
  +    if (info->date == APR_DATE_BAD) {  /* No, or bad date */
           char *dates;
           /* no date header! */
  -        /* add one; N.B. use the time _now_ rather than when we were checking the cache */
  +        /* add one; N.B. use the time _now_ rather than when we were checking
  +         * the cache 
  +         */
           date = now;
           dates = apr_pcalloc(r->pool, MAX_STRING_LEN);
           apr_rfc822_date(dates, now);
  @@ -605,11 +652,13 @@
       /* XXX FIXME we're referencing date on a path where we didn't set it */
       if (lastmod != APR_DATE_BAD && lastmod > date)
       {
  -	/* if its in the future, then replace by date */
  +        /* if its in the future, then replace by date */
           lastmod = date;
           lastmods = dates;
  -        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
  -                     "cache: Last modified is in the future, replacing with now");
  +        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, 
  +                     r->server,
  +                     "cache: Last modified is in the future, "
  +                     "replacing with now");
       }
       info->lastmod = lastmod;
   
  @@ -638,11 +687,12 @@
       info->expire = exp;
   
       info->content_type = apr_pstrdup(r->pool, r->content_type);
  +    info->filename = apr_pstrdup(r->pool, r->filename );
   
       /*
        * Write away header information to cache.
        */
  -    cache_write_entity_headers(cache->handle, r, info, r->headers_out);
  +    cache_write_entity_headers(cache->handle, r, info);
       cache_write_entity_body(cache->handle, in);    
       return ap_pass_brigade(f->next, in);
   }
  @@ -673,6 +723,8 @@
       /* default percentage to force cache completion */
       ps->complete = DEFAULT_CACHE_COMPLETION;
       ps->complete_set = 0;
  +    ps->no_last_mod_ignore_set = 0;
  +    ps->no_last_mod_ignore = 0;
       return ps;
   }
   
  @@ -683,11 +735,16 @@
       cache_server_conf *overrides = (cache_server_conf *) overridesv;
   
       /* 1 if the cache is enabled, 0 otherwise */
  -    ps->cacheon = (overrides->cacheon_set == 0) ? base->cacheon : overrides->cacheon;
  +    ps->cacheon = 
  +        (overrides->cacheon_set == 0) ? base->cacheon : overrides->cacheon;
       /* array of URL prefixes for which caching is disabled */
  -    ps->cachedisable = ap_append_arrays(p, base->cachedisable, overrides->cachedisable);
  +    ps->cachedisable = ap_append_arrays(p, 
  +                                        base->cachedisable, 
  +                                        overrides->cachedisable);
       /* array of URL prefixes for which caching is enabled */
  -    ps->cacheenable = ap_append_arrays(p, base->cacheenable, overrides->cacheenable);
  +    ps->cacheenable = ap_append_arrays(p, 
  +                                       base->cacheenable, 
  +                                       overrides->cacheenable);
       /* maximum time to cache a document */
       ps->maxex = (overrides->maxex_set == 0) ? base->maxex : overrides->maxex;
       /* default time to cache a document */
  @@ -695,15 +752,31 @@
       /* factor used to estimate Expires date from LastModified date */
       ps->factor = (overrides->factor_set == 0) ? base->factor : overrides->factor;
       /* default percentage to force cache completion */
  -    ps->complete = (overrides->complete_set == 0) ? base->complete : overrides->complete;
  +    ps->complete =
  +        (overrides->complete_set == 0) ? base->complete : overrides->complete;
   
  +    ps->no_last_mod_ignore =
  +        (overrides->no_last_mod_ignore_set) ? 
  +                    base->no_last_mod_ignore : 
  +                    overrides->no_last_mod_ignore;
       return ps;
   }
  +static const char
  +*set_cache_ignore_no_last_mod( cmd_parms *parms, void *dummy, int flag)
  +{
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
   
  +    conf->no_last_mod_ignore = 1;
  +    conf->no_last_mod_ignore_set = 1;
  +    return NULL;
  +
  +}
   static const char
   *set_cache_on(cmd_parms *parms, void *dummy, int flag)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config,
  +                                                   &cache_module);
   
       conf->cacheon = 1;
       conf->cacheon_set = 1;
  @@ -711,9 +784,13 @@
   }
   
   static const char
  -*add_cache_enable(cmd_parms *parms, void *dummy, const char *type, const char *url)
  +*add_cache_enable(cmd_parms *parms, 
  +                  void *dummy, 
  +                  const char *type, 
  +                  const char *url)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config,
  +                                                   &cache_module);
       struct cache_enable *new;
   
       new = apr_array_push(conf->cacheenable);
  @@ -725,7 +802,8 @@
   static const char
   *add_cache_disable(cmd_parms *parms, void *dummy, const char *url)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
       struct cache_enable *new;
   
       new = apr_array_push(conf->cachedisable);
  @@ -736,7 +814,8 @@
   static const char
   *set_cache_maxex(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config,
  +                                                   &cache_module);
       double val;
   
       if (sscanf(arg, "%lg", &val) != 1)
  @@ -748,7 +827,8 @@
   static const char
   *set_cache_maxex_min(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config,
  +                                                   &cache_module);
       long val;
   
       val = atol(arg);
  @@ -761,7 +841,8 @@
   static const char
   *set_cache_defex(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
       double val;
   
       if (sscanf(arg, "%lg", &val) != 1)
  @@ -773,7 +854,8 @@
   static const char
   *set_cache_defex_min(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
       long val;
   
       val = atol(arg);
  @@ -786,7 +868,8 @@
   static const char
   *set_cache_factor(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
       double val;
   
       if (sscanf(arg, "%lg", &val) != 1)
  @@ -799,7 +882,8 @@
   static const char
   *set_cache_complete(cmd_parms *parms, void *dummy, const char *arg)
   {
  -    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, &cache_module);
  +    cache_server_conf *conf = ap_get_module_config(parms->server->module_config, 
  +                                                   &cache_module);
       int val;
   
       if (sscanf(arg, "%u", &val) != 1)
  @@ -835,6 +919,9 @@
        "The default time in hours to cache a document"),
        AP_INIT_TAKE1("CacheDefaultExpireMin", set_cache_defex_min, NULL, RSRC_CONF,
        "The default time in Minutes to cache a document"),
  +     AP_INIT_TAKE1("CacheIgnoreNoLastMod", set_cache_ignore_no_last_mod, NULL, 
  +             RSRC_CONF, 
  +             "Ignore Responses where there is no Last Modified Header"),
   
       AP_INIT_TAKE1("CacheLastModifiedFactor", set_cache_factor, NULL, RSRC_CONF,
        "The factor used to estimate Expires date from LastModified date"),
  @@ -853,19 +940,26 @@
        * XXX The cache filters need to run right after the handlers and before
        * any other filters. Consider creating AP_FTYPE_CACHE for this purpose.
        * Make them AP_FTYPE_CONTENT for now.
  +     * XXX ianhH:they should run AFTER all the other content filters.
        */
  -    ap_register_output_filter("CACHE_IN", ap_cache_in_filter, AP_FTYPE_CONTENT);
  -    ap_register_output_filter("CACHE_OUT", ap_cache_out_filter, AP_FTYPE_CONTENT);
  -    ap_register_output_filter("CACHE_CONDITIONAL", ap_cache_conditional_filter, AP_FTYPE_CONTENT);
  +    ap_register_output_filter("CACHE_IN", 
  +                              ap_cache_in_filter, 
  +                              AP_FTYPE_CONTENT+1);
  +    ap_register_output_filter("CACHE_OUT", 
  +                              ap_cache_out_filter, 
  +                              AP_FTYPE_CONTENT+1);
  +    ap_register_output_filter("CACHE_CONDITIONAL", 
  +                              ap_cache_conditional_filter, 
  +                              AP_FTYPE_CONTENT+1);
   }
   
   module AP_MODULE_DECLARE_DATA cache_module =
   {
       STANDARD20_MODULE_STUFF,
  -    NULL,			/* create per-directory config structure */
  -    NULL,			/* merge per-directory config structures */
  -    create_cache_config,	/* create per-server config structure */
  -    merge_cache_config,		/* merge per-server config structures */
  -    cache_cmds,			/* command apr_table_t */
  +    NULL,                   /* create per-directory config structure */
  +    NULL,                   /* merge per-directory config structures */
  +    create_cache_config,    /* create per-server config structure */
  +    merge_cache_config,     /* merge per-server config structures */
  +    cache_cmds,             /* command apr_table_t */
       register_hooks
   };
  
  
  
  1.13      +20 -29    httpd-2.0/modules/experimental/mod_cache.h
  
  Index: mod_cache.h
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_cache.h,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- mod_cache.h	4 Jan 2002 17:58:36 -0000	1.12
  +++ mod_cache.h	25 Jan 2002 20:09:33 -0000	1.13
  @@ -142,12 +142,15 @@
       apr_array_header_t *cachedisable;	/* URLs not to cache */
       apr_time_t maxex;			/* Maximum time to keep cached files in msecs */
       int maxex_set;
  -    apr_time_t defex;			/* default time to keep cached file in msecs */
  +    apr_time_t defex;           /* default time to keep cached file in msecs */
       int defex_set;
  -    double factor;			/* factor for estimating expires date */
  +    double factor;              /* factor for estimating expires date */
       int factor_set;
  -    int complete;			/* Force cache completion after this point */
  +    int complete;               /* Force cache completion after this point */
       int complete_set;
  +    /* ignore the last-modified header when deciding to cache this request */
  +    int no_last_mod_ignore_set;
  +    int no_last_mod_ignore; 
   } cache_server_conf;
   
   /* cache info information */
  @@ -155,7 +158,8 @@
   struct cache_info {
       const char *content_type;
       const char *etag;
  -    const char *lastmods;	/* last modified of cache entity */
  +    const char *lastmods;     /* last modified of cache entity */
  +    const char *filename;   
       apr_time_t date;
       apr_time_t lastmod;
       char lastmod_str[APR_RFC822_DATE_LEN];
  @@ -180,9 +184,9 @@
   struct cache_handle {
       cache_object_t *cache_obj;
       int (*remove_entity) (cache_handle_t *h);
  -    int (*write_headers)(cache_handle_t *h, request_rec *r, cache_info *i, apr_table_t *headers);
  +    int (*write_headers)(cache_handle_t *h, request_rec *r, cache_info *i);
       int (*write_body)(cache_handle_t *h, apr_bucket_brigade *b);
  -    int (*read_headers) (cache_handle_t *h, request_rec *r, apr_table_t *headers);
  +    int (*read_headers) (cache_handle_t *h, request_rec *r);
       int (*read_body) (cache_handle_t *h, apr_bucket_brigade *bb); 
   };
   
  @@ -210,12 +214,16 @@
   int cache_create_entity(request_rec *r, const char *types, char *url, apr_size_t size);
   int cache_remove_entity(request_rec *r, const char *types, cache_handle_t *h);
   int cache_select_url(request_rec *r, const char *types, char *url);
  +/**
  + * create a key for the cache based on the request record
  + * this is the 'default' version, which can be overridden by a default function
  + */
  +const char* cache_create_key( request_rec*r );
   
  -apr_status_t cache_write_entity_headers(cache_handle_t *h, request_rec *r, cache_info *info, 
  -                                        apr_table_t *headers);
  +apr_status_t cache_write_entity_headers(cache_handle_t *h, request_rec *r, cache_info *info);
   apr_status_t cache_write_entity_body(cache_handle_t *h, apr_bucket_brigade *bb);
   
  -apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r, apr_table_t **headers);
  +apr_status_t cache_read_entity_headers(cache_handle_t *h, request_rec *r);
   apr_status_t cache_read_entity_body(cache_handle_t *h, apr_bucket_brigade *bb);
   
   
  @@ -244,28 +252,11 @@
   
   APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, create_entity, 
                             (cache_handle_t *h, const char *type,
  -                           char *url, apr_size_t len))
  +                           const char *urlkey, apr_size_t len))
   APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, open_entity,  
                             (cache_handle_t *h, const char *type,
  -                           char *url))
  +                           const char *urlkey))
   APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, remove_url, 
  -                          (const char *type, char *url))
  -
  -#if 0
  -APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, remove_entity, 
  -                          (cache_handle *h))
  -APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, read_entity_headers, 
  -                          (cache_handle *h, cache_info **info,
  -                           apr_table_t **headers))
  -APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, read_entity_body, 
  -                          (cache_handle *h,
  -                           apr_bucket_brigade *out))
  -APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, write_entity_headers, 
  -                          (cache_handle *h, cache_info *info,
  -                           apr_table_t *headers))
  -APR_DECLARE_EXTERNAL_HOOK(cache, CACHE, int, write_entity_body, 
  -                          (cache_handle *h,
  -                           apr_bucket_brigade *in))
  -#endif
  +                          (const char *type, const char *urlkey))
   
   #endif /*MOD_CACHE_H*/
  
  
  
  1.13      +154 -98   httpd-2.0/modules/experimental/mod_mem_cache.c
  
  Index: mod_mem_cache.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/experimental/mod_mem_cache.c,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- mod_mem_cache.c	4 Jan 2002 17:58:36 -0000	1.12
  +++ mod_mem_cache.c	25 Jan 2002 20:09:33 -0000	1.13
  @@ -66,7 +66,7 @@
   #error This module does not currently compile unless you have a thread-capable APR. Sorry!
   #endif
   
  -#define MAX_CACHE 5000
  +static apr_size_t max_cache_entry_size = 5000;
   module AP_MODULE_DECLARE_DATA mem_cache_module;
   
   /* 
  @@ -93,8 +93,12 @@
   
   typedef struct mem_cache_object {
       cache_type_e type;
  -    apr_ssize_t num_headers;
  -    cache_header_tbl_t *tbl;
  +    apr_ssize_t num_header_out;
  +    apr_ssize_t num_subprocess_env;
  +    apr_ssize_t num_notes;
  +    cache_header_tbl_t *header_out;
  +    cache_header_tbl_t *subprocess_env;
  +    cache_header_tbl_t *notes;
       apr_size_t m_len;
       void *m;
   } mem_cache_object_t;
  @@ -113,10 +117,9 @@
   
   /* Forward declarations */
   static int remove_entity(cache_handle_t *h);
  -static int write_headers(cache_handle_t *h, request_rec *r, cache_info *i,
  -                         apr_table_t *headers);
  +static int write_headers(cache_handle_t *h, request_rec *r, cache_info *i);
   static int write_body(cache_handle_t *h, apr_bucket_brigade *b);
  -static int read_headers(cache_handle_t *h, request_rec *r, apr_table_t *headers);
  +static int read_headers(cache_handle_t *h, request_rec *r);
   static int read_body(cache_handle_t *h, apr_bucket_brigade *bb);
   
   static void cleanup_cache_object(cache_object_t *obj)
  @@ -166,9 +169,18 @@
       if (mobj->m) {
           free(mobj->m);
       }
  -
  +    /* XXX should freeing of the info be done here or in cache_storage ? 
  +    if (obj->info.content_type ) {
  +        free((char*)obj->info.content_type );
  +        obj->info.content_type =NULL;
  +    }
  +    if (obj->info.filename ) {
  +        free( (char*)obj->info.filename );
  +        obj->info.filename= NULL;
  +    }
  +    */
       /* XXX Cleanup the headers */
  -    if (mobj->num_headers) {
  +    if (mobj->num_header_out) {
           
       }
       free(mobj);
  @@ -199,10 +211,6 @@
   
       sconf = apr_pcalloc(p, sizeof(mem_cache_conf));
       sconf->space = DEFAULT_CACHE_SPACE;
  -#if 0
  -    sconf->maxexpire = DEFAULT_CACHE_MAXEXPIRE;
  -    sconf->defaultexpire = DEFAULT_CACHE_EXPIRE;
  -#endif
   
       ap_mpm_query(AP_MPMQ_IS_THREADED, &threaded_mpm);
       if (threaded_mpm) {
  @@ -214,7 +222,10 @@
       return sconf;
   }
   
  -static int create_entity(cache_handle_t *h, const char *type, char *key, apr_size_t len) 
  +static int create_entity(cache_handle_t *h, 
  +                         const char *type, 
  +                         const char *key, 
  +                         apr_size_t len) 
   {
       cache_object_t *obj, *tmp_obj;
       mem_cache_object_t *mobj;
  @@ -226,7 +237,7 @@
       /* XXX Check len to see if it is withing acceptable bounds 
        * max cache check should be configurable variable.
        */
  -    if (len < 0 || len > MAX_CACHE) {
  +    if (len < 0 || len > max_cache_entry_size) {
           return DECLINED;
       }
       /* XXX Check total cache size and number of entries. Are they within the
  @@ -256,7 +267,9 @@
           cleanup_cache_object(obj);
       }
       memset(mobj,'\0', sizeof(*mobj));
  -    obj->vobj = mobj;    /* Reference the mem_cache_object_t out of cache_object_t */
  +    obj->vobj = mobj;    /* Reference the mem_cache_object_t out of 
  +                          * cache_object_t 
  +                          */
       mobj->m_len = len;    /* Duplicates info in cache_object_t info */
   
   
  @@ -268,7 +281,9 @@
       if (sconf->lock) {
           apr_thread_mutex_lock(sconf->lock);
       }
  -    tmp_obj = (cache_object_t *) apr_hash_get(sconf->cacheht, key, APR_HASH_KEY_STRING);
  +    tmp_obj = (cache_object_t *) apr_hash_get(sconf->cacheht, 
  +                                              key, 
  +                                              APR_HASH_KEY_STRING);
       if (!tmp_obj) {
           apr_hash_set(sconf->cacheht, obj->key, strlen(obj->key), obj);
       }
  @@ -296,7 +311,7 @@
       return OK;
   }
   
  -static int open_entity(cache_handle_t *h, const char *type, char *key) 
  +static int open_entity(cache_handle_t *h, const char *type, const char *key) 
   {
       cache_object_t *obj;
   
  @@ -307,7 +322,9 @@
       if (sconf->lock) {
           apr_thread_mutex_lock(sconf->lock);
       }
  -    obj = (cache_object_t *) apr_hash_get(sconf->cacheht, key, APR_HASH_KEY_STRING);
  +    obj = (cache_object_t *) apr_hash_get(sconf->cacheht, 
  +                                          key, 
  +                                          APR_HASH_KEY_STRING);
       if (sconf->lock) {
           apr_thread_mutex_unlock(sconf->lock);
       }
  @@ -343,9 +360,69 @@
       
       return OK;
   }
  +static int serialize_table( cache_header_tbl_t **obj, 
  +                            int*nelts, 
  +                            apr_table_t *table) 
  +{
  +   apr_table_entry_t *elts = (apr_table_entry_t *) table->a.elts;
  +   apr_ssize_t i;
  +   apr_size_t len = 0;
  +   apr_size_t idx = 0;
  +   char *buf;
  +   
  +   *nelts = table->a.nelts;
  +   if (*nelts ==0 ) {
  +       *obj=NULL;
  +       return OK;
  +   }
  +    *obj = malloc(sizeof(cache_header_tbl_t) * table->a.nelts);
  +    if (NULL == *obj) {
  +        /* cleanup_cache_obj(h->cache_obj); */
  +        return DECLINED;
  +    }
  +    for (i = 0; i < table->a.nelts; ++i) {
  +        len += strlen(elts[i].key);
  +        len += strlen(elts[i].val);
  +        len += 2;  /* Extra space for NULL string terminator for key and val */
  +    }
   
  +    /* Transfer the headers into a contiguous memory block */
  +    buf = malloc(len);
  +    if (!buf) {
  +        free(obj);
  +        *obj = NULL;
  +        /* cleanup_cache_obj(h->cache_obj); */
  +        return DECLINED;
  +    }
  +
  +    for (i = 0; i < *nelts; ++i) {
  +        (*obj)[i].hdr = &buf[idx];
  +        len = strlen(elts[i].key) + 1;              /* Include NULL terminator */
  +        strncpy(&buf[idx], elts[i].key, len);
  +        idx+=len;
  +
  +        (*obj)[i].val = &buf[idx];
  +        len = strlen(elts[i].val) + 1;
  +        strncpy(&buf[idx], elts[i].val, len);
  +        idx+=len;
  +    }
  +    return OK;
  + 
  +}
  +static int unserialize_table( cache_header_tbl_t *ctbl, 
  +                              int num_headers, 
  +                              apr_table_t *t )
  +{
  +    int i;
  +
  +    for (i = 0; i < num_headers; ++i) {
  +        apr_table_setn(t, ctbl[i].hdr, ctbl[i].val);
  +    } 
  +
  +    return OK;
  +}
   /* Define request processing hook handlers */
  -static int remove_url(const char *type, char *key) 
  +static int remove_url(const char *type, const char *key) 
   {
       cache_object_t *obj;
   
  @@ -363,7 +440,9 @@
       if (sconf->lock) {
           apr_thread_mutex_lock(sconf->lock);
       }
  -    obj = (cache_object_t *) apr_hash_get(sconf->cacheht, key, APR_HASH_KEY_STRING);
  +    obj = (cache_object_t *) apr_hash_get(sconf->cacheht, 
  +                                          key, 
  +                                          APR_HASH_KEY_STRING);
       if (sconf->lock) {
           apr_thread_mutex_unlock(sconf->lock);
       }
  @@ -386,16 +465,25 @@
       return OK;
   }
   
  -static int read_headers(cache_handle_t *h, request_rec *r, apr_table_t *headers) 
  +static int read_headers(cache_handle_t *h, request_rec *r) 
   {
  +    int rc;
       mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;
  -    int i;
   
  -    for (i = 0; i < mobj->num_headers; ++i) {
  -        apr_table_setn(headers, mobj->tbl[i].hdr, mobj->tbl[i].val);
  -    } 
  +    r->headers_out = apr_table_make(r->pool,mobj->num_header_out);
  +    r->subprocess_env = apr_table_make(r->pool, mobj->num_subprocess_env);
  +    r->notes = apr_table_make(r->pool, mobj->num_notes);
  +    rc = unserialize_table( mobj->header_out,
  +                            mobj->num_header_out, 
  +                            r->headers_out);
  +    rc = unserialize_table( mobj->subprocess_env, 
  +                            mobj->num_subprocess_env, 
  +                            r->subprocess_env);
  +    rc = unserialize_table( mobj->notes,
  +                            mobj->num_notes,
  +                            r->notes);
  +    return rc;
   
  -    return OK;
   }
   
   static int read_body(cache_handle_t *h, apr_bucket_brigade *bb) 
  @@ -411,49 +499,33 @@
       return OK;
   }
   
  -static int write_headers(cache_handle_t *h, request_rec *r, cache_info *info, apr_table_t *headers)
  +
  +static int write_headers(cache_handle_t *h, request_rec *r, cache_info *info)
   {
       cache_object_t *obj = h->cache_obj;
       mem_cache_object_t *mobj = (mem_cache_object_t*) h->cache_obj->vobj;
  -    apr_table_entry_t *elts = (apr_table_entry_t *) headers->a.elts;
  -    apr_ssize_t i;
  -    apr_size_t len = 0;
  -    apr_size_t idx = 0;
  -    char *buf;
  +    int rc;
   
       /* Precompute how much storage we need to hold the headers */
  -    mobj->tbl = malloc(sizeof(cache_header_tbl_t) * headers->a.nelts);
  -    if (NULL == mobj->tbl) {
  -        /* cleanup_cache_obj(h->cache_obj); */
  -        return DECLINED;
  +    rc = serialize_table(&mobj->header_out, 
  +                         &mobj->num_header_out, 
  +                         r->headers_out);   
  +    if (rc != OK ) {
  +        return rc;
       }
  -    for (i = 0; i < headers->a.nelts; ++i) {
  -        len += strlen(elts[i].key);
  -        len += strlen(elts[i].val);
  -        len += 2;        /* Extra space for NULL string terminator for key and val */
  +    rc = serialize_table(&mobj->subprocess_env,
  +                         &mobj->num_subprocess_env, 
  +                         r->subprocess_env );
  +    if (rc != OK ) {
  +        return rc;
       }
   
  -    /* Transfer the headers into a contiguous memory block */
  -    buf = malloc(len);
  -    if (!buf) {
  -        free(mobj->tbl);
  -        mobj->tbl = NULL;
  -        /* cleanup_cache_obj(h->cache_obj); */
  -        return DECLINED;
  -    }
  -    mobj->num_headers = headers->a.nelts;
  -    for (i = 0; i < mobj->num_headers; ++i) {
  -        mobj->tbl[i].hdr = &buf[idx];
  -        len = strlen(elts[i].key) + 1;              /* Include NULL terminator */
  -        strncpy(&buf[idx], elts[i].key, len);
  -        idx+=len;
  -
  -        mobj->tbl[i].val = &buf[idx];
  -        len = strlen(elts[i].val) + 1;
  -        strncpy(&buf[idx], elts[i].val, len);
  -        idx+=len;
  +    rc = serialize_table(&mobj->notes, &mobj->num_notes, r->notes);
  +    if (rc != OK ) {
  +        return rc;
       }
   
  + 
       /* Init the info struct */
       if (info->date) {
           obj->info.date = info->date;
  @@ -472,6 +544,15 @@
           }
           strcpy((char*) obj->info.content_type, info->content_type);
       }
  +    if ( info->filename) {
  +        obj->info.filename = (char*) malloc(strlen(info->filename )+1);
  +        if (!obj->info.filename ) {
  +            free( (char*)obj->info.content_type );
  +            obj->info.content_type =NULL;
  +            return DECLINED;
  +        }
  +        strcpy((char*) obj->info.filename, info->filename );
  +    }
   
       return OK;
   }
  @@ -522,7 +603,6 @@
            */
           AP_DEBUG_ASSERT(h->cache_obj->count > mobj->m_len);
       }
  -
       return OK;
   }
   
  @@ -537,45 +617,19 @@
       sconf->space = val;
       return NULL;
   }
  -#if 0
  -static const char
  -*set_cache_factor(cmd_parms *parms, void *dummy, char *arg)
  -{
  -    double val;
  -
  -    if (sscanf(arg, "%lg", &val) != 1)
  -        return "CacheLastModifiedFactor value must be a float";
  -    sconf->lmfactor = val;
  +static const char 
  +*set_cache_entry_size(cmd_parms *parms, void *in_struct_ptr, const char *arg)
  +{
  +    int val;
   
  +    if (sscanf(arg, "%d", &val) != 1) {
  +        return "CacheSize value must be an integer (bytes)";
  +    }
  +    max_cache_entry_size = val;
       return NULL;
   }
  -#endif
  -#if 0
  -static const char
  -*set_cache_maxex(cmd_parms *parms, void *dummy, char *arg)
  -{
  -    mem_cache_conf *pc = ap_get_module_config(parms->server->module_config, &mem_cache_module);
  -    double val;
  -
  -    if (sscanf(arg, "%lg", &val) != 1)
  -        return "CacheMaxExpire value must be a float";
  -    sconf->maxexpire = (apr_time_t) (val * MSEC_ONE_HR);
  -    return NULL;
  -}
  -#endif
  -#if 0
  -static const char
  -*set_cache_defex(cmd_parms *parms, void *dummy, char *arg)
  -{
  -    mem_cache_conf *pc = ap_get_module_config(parms->server->module_config, &mem_cache_module);
  -    double val;
  -
  -    if (sscanf(arg, "%lg", &val) != 1)
  -        return "CacheDefaultExpire value must be a float";
  -    pc->defaultexpire = (apr_time_t) (val * MSEC_ONE_HR);
  -    return NULL;
  -}
  -#endif
  +
  +
   static const command_rec cache_cmds[] =
   {
       /* XXX
  @@ -585,8 +639,10 @@
        * max entry size, and max size of the cache should
        * be managed by this module. 
        */
  -    AP_INIT_TAKE1("CacheSizeMem", set_cache_size, NULL, RSRC_CONF,
  -     "The maximum disk space used by the cache in Kb"),
  +    AP_INIT_TAKE1("CacheMemSize", set_cache_size, NULL, RSRC_CONF,
  +     "The maximum space used by the cache in Kb"),
  +    AP_INIT_TAKE1("CacheMemEntrySize", set_cache_entry_size, NULL, RSRC_CONF,
  +     "The maximum size (in bytes) that a entry can take"),
       {NULL}
   };