The initial cache load caches whatever is in subprocess_env. On the next request, mod_cache discovers that the cache entry is stale, but by the time it has figured out that it needs to DECLINE the request, it has replaced r->subprocess_env with what was in the stale cache entry. Whatever is in the subprocess_env table when the quick handler DECLINES stays there and new entries are added by Apache during normal (uncached) file handling. The result is that when the cache_in_filter is run to cache the new response, subprocess_env contains the values out of the stale cache entry -and- the new values added by default_handling. When the new cache entry becomes stale, the cycle starts again and sunprocess_env grows more.
I really don't have much time to pursue this so here is a patch that:
1. saves some tables of interest from the request_rec at entry to the cache_handler. These value are restored if the cache_handler DECLINES
2. Hacks out a bunch of code that I cannot quite grok and that I am pretty sure is causing more problems that it is solving.
mod_cache needs some serious work before it is ready to come out of experimental.
Bill
RCS file: /cvs/phoenix/2.0.47/modules/experimental/mod_cache.c,v
retrieving revision 1.2
diff -u -r1.2 mod_cache.c
--- mod_cache.c 5 Mar 2004 02:33:46 -0000 1.2
+++ mod_cache.c 6 Mar 2004 21:11:23 -0000
@@ -57,6 +57,12 @@
cache_info *info = NULL;
cache_request_rec *cache;
cache_server_conf *conf;
+ /* Hack till we come up with a better solution */
+
+ apr_table_t *err_headers_out = r->err_headers_out;
+ apr_table_t *notes = r->notes;
+ apr_table_t *subprocess_env = r->subprocess_env;
+ apr_table_t *headers_out = r->headers_out; conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
&cache_module);
@@ -151,18 +157,7 @@
*/ rv = cache_select_url(r, cache->types, url);
- if (DECLINED == rv) {
- if (!lookup) {
- /* no existing cache file */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: no cache - add cache_in filter and DECLINE");
- /* add cache_in filter to cache this request */
- ap_add_output_filter_handle(cache_in_filter_handle, NULL, r,
- r->connection);
- }
- return DECLINED;
- }
- else if (OK == rv) {
+ if (OK == rv) {
/* RFC2616 13.2 - Check cache object expiration */
cache->fresh = ap_cache_check_freshness(cache, r);
if (cache->fresh) {
@@ -174,127 +169,69 @@
return OK;
}
rv = ap_meets_conditions(r);
- if (rv != OK) {
+ if (rv == OK) {
+ /* Meets conditions or is not conditional */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: fresh cache - returning status %d", rv);
- return rv;
- }
+ "cache: fresh cache - add cache_out filter and "
+ "handle request");- /* - * Not a conditionl request. Serve up the content - */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "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. + */ + ap_run_insert_filter(r); + ap_add_output_filter_handle(cache_out_filter_handle, NULL, + r, r->connection);
- /* We are in the quick handler hook, which means that no output
- * filters have been set. So lets run the insert_filter hook.
- */
- ap_run_insert_filter(r);
- ap_add_output_filter_handle(cache_out_filter_handle, NULL,
- r, r->connection);
-
- /* kick off the filter stack */
- out = apr_brigade_create(r->pool, c->bucket_alloc);
- 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);
- return rv;
+ /* kick off the filter stack */
+ out = apr_brigade_create(r->pool, c->bucket_alloc);
+ rv = ap_pass_brigade(r->output_filters, out);
+
+ if (rv != APR_SUCCESS) {
+ /* Is this right??? Is rv returned to the client? That would be
odd */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: error returned while trying to return %s "
+ "cached data",
+ cache->type);
+ return rv;
+ }
+ return OK;
}
- return OK;
+ /* If the cached entry does not meet conditions, DECLINE
+ * the request and give the origin server a shot at serving it.
+ * Do we want to remove the entry from the cache?
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: cache object does not meet conditions");
}
else {
- if (!r->err_headers_out) {
- r->err_headers_out = apr_table_make(r->pool, 3);
- }
- /* stale data available */
- if (lookup) {
- return DECLINED;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: stale cache - test conditional");
- /* if conditional request */
- if (ap_cache_request_is_conditional(r)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: conditional - add cache_in filter and "
- "DECLINE");
- /* Why not add CACHE_CONDITIONAL? */
+ /*
+ * We have a stale cache entry. Temporarily hack ...
+ *
+ * You can never be wrong declining to serve up stale bytes out of the
+ * cache (pretty sure anyway!) If the entry is stale, restore the
+ * request_rec to it's original state upon entry to this function and
+ * return DECLINE. We'll add the optimization to serve up conditionl
+ * stale bytes when we figure out how to do it right.
+ */
+ if (!lookup) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: cache object is stale. Reloading from origin
server.");
ap_add_output_filter_handle(cache_in_filter_handle, NULL,
r, r->connection);
-
- return DECLINED;
- }
- /* else if non-conditional request */
- else {
- /* Temporarily hack this to work the way it had been. Its broken,
- * but its broken the way it was before. I'm working on figuring
- * out why the filter add in the conditional filter doesn't work. pjr
- *
- * info = &(cache->handle->cache_obj->info);
- *
- * Uncomment the above when the code in
cache_conditional_filter_handle
- * is properly fixed... pjr
- */
-
- /* fudge response into a conditional */
- if (info && info->etag) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 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, 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);
- }
- else {
- /* something else - pretend there was no cache */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - no cached "
- "etag/lastmods - add cache_in and DECLINE");
-
- ap_add_output_filter_handle(cache_in_filter_handle, NULL,
- r, r->connection);
-
- return DECLINED;
- }
- /* add cache_conditional filter */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - add cache_conditional "
- "and DECLINE");
- ap_add_output_filter_handle(cache_conditional_filter_handle,
- NULL,
- r,
- r->connection);
-
- return DECLINED;
}
}
}
- 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);
- return DECLINED;
- }
+ else if (rv == DECLINED) {
+ ap_add_output_filter_handle(cache_in_filter_handle, NULL,
+ r, r->connection);
+ }
+ /* Restore the request_rec back to it's original state */
+ r->headers_out = headers_out;
+ r->err_headers_out = err_headers_out;
+ r->notes = notes;
+ r->subprocess_env = subprocess_env;
+
+ return DECLINED;
}/*
? cache.tar
? mod_cache.old.c
? mod_cache.patch
? mod_mem_cache.old.c
Index: mod_cache.c
===================================================================
RCS file: /cvs/phoenix/2.0.47/modules/experimental/mod_cache.c,v
retrieving revision 1.2
diff -u -r1.2 mod_cache.c
--- mod_cache.c 5 Mar 2004 02:33:46 -0000 1.2
+++ mod_cache.c 6 Mar 2004 21:11:23 -0000
@@ -57,6 +57,12 @@
cache_info *info = NULL;
cache_request_rec *cache;
cache_server_conf *conf;
+ /* Hack till we come up with a better solution */
+
+ apr_table_t *err_headers_out = r->err_headers_out;
+ apr_table_t *notes = r->notes;
+ apr_table_t *subprocess_env = r->subprocess_env;
+ apr_table_t *headers_out = r->headers_out;
conf = (cache_server_conf *) ap_get_module_config(r->server->module_config,
&cache_module);
@@ -151,18 +157,7 @@
*/
rv = cache_select_url(r, cache->types, url);
- if (DECLINED == rv) {
- if (!lookup) {
- /* no existing cache file */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: no cache - add cache_in filter and DECLINE");
- /* add cache_in filter to cache this request */
- ap_add_output_filter_handle(cache_in_filter_handle, NULL, r,
- r->connection);
- }
- return DECLINED;
- }
- else if (OK == rv) {
+ if (OK == rv) {
/* RFC2616 13.2 - Check cache object expiration */
cache->fresh = ap_cache_check_freshness(cache, r);
if (cache->fresh) {
@@ -174,127 +169,69 @@
return OK;
}
rv = ap_meets_conditions(r);
- if (rv != OK) {
+ if (rv == OK) {
+ /* Meets conditions or is not conditional */
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: fresh cache - returning status %d", rv);
- return rv;
- }
+ "cache: fresh cache - add cache_out filter and "
+ "handle request");
- /*
- * Not a conditionl request. Serve up the content
- */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "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.
+ */
+ ap_run_insert_filter(r);
+ ap_add_output_filter_handle(cache_out_filter_handle, NULL,
+ r, r->connection);
- /* We are in the quick handler hook, which means that no output
- * filters have been set. So lets run the insert_filter hook.
- */
- ap_run_insert_filter(r);
- ap_add_output_filter_handle(cache_out_filter_handle, NULL,
- r, r->connection);
-
- /* kick off the filter stack */
- out = apr_brigade_create(r->pool, c->bucket_alloc);
- 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);
- return rv;
+ /* kick off the filter stack */
+ out = apr_brigade_create(r->pool, c->bucket_alloc);
+ rv = ap_pass_brigade(r->output_filters, out);
+
+ if (rv != APR_SUCCESS) {
+ /* Is this right??? Is rv returned to the client? That would be
odd */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: error returned while trying to return %s "
+ "cached data",
+ cache->type);
+ return rv;
+ }
+ return OK;
}
- return OK;
+ /* If the cached entry does not meet conditions, DECLINE
+ * the request and give the origin server a shot at serving it.
+ * Do we want to remove the entry from the cache?
+ */
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: cache object does not meet conditions");
}
else {
- if (!r->err_headers_out) {
- r->err_headers_out = apr_table_make(r->pool, 3);
- }
- /* stale data available */
- if (lookup) {
- return DECLINED;
- }
-
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
- "cache: stale cache - test conditional");
- /* if conditional request */
- if (ap_cache_request_is_conditional(r)) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: conditional - add cache_in filter and "
- "DECLINE");
- /* Why not add CACHE_CONDITIONAL? */
+ /*
+ * We have a stale cache entry. Temporarily hack ...
+ *
+ * You can never be wrong declining to serve up stale bytes out of the
+ * cache (pretty sure anyway!) If the entry is stale, restore the
+ * request_rec to it's original state upon entry to this function and
+ * return DECLINE. We'll add the optimization to serve up conditionl
+ * stale bytes when we figure out how to do it right.
+ */
+ if (!lookup) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
+ "cache: cache object is stale. Reloading from origin
server.");
ap_add_output_filter_handle(cache_in_filter_handle, NULL,
r, r->connection);
-
- return DECLINED;
- }
- /* else if non-conditional request */
- else {
- /* Temporarily hack this to work the way it had been. Its broken,
- * but its broken the way it was before. I'm working on figuring
- * out why the filter add in the conditional filter doesn't work. pjr
- *
- * info = &(cache->handle->cache_obj->info);
- *
- * Uncomment the above when the code in
cache_conditional_filter_handle
- * is properly fixed... pjr
- */
-
- /* fudge response into a conditional */
- if (info && info->etag) {
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 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, 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);
- }
- else {
- /* something else - pretend there was no cache */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - no cached "
- "etag/lastmods - add cache_in and DECLINE");
-
- ap_add_output_filter_handle(cache_in_filter_handle, NULL,
- r, r->connection);
-
- return DECLINED;
- }
- /* add cache_conditional filter */
- ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
- r->server,
- "cache: nonconditional - add cache_conditional "
- "and DECLINE");
- ap_add_output_filter_handle(cache_conditional_filter_handle,
- NULL,
- r,
- r->connection);
-
- return DECLINED;
}
}
}
- 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);
- return DECLINED;
- }
+ else if (rv == DECLINED) {
+ ap_add_output_filter_handle(cache_in_filter_handle, NULL,
+ r, r->connection);
+ }
+ /* Restore the request_rec back to it's original state */
+ r->headers_out = headers_out;
+ r->err_headers_out = err_headers_out;
+ r->notes = notes;
+ r->subprocess_env = subprocess_env;
+
+ return DECLINED;
}
/*
