Skip to content

Commit ab13cb3

Browse files
author
Justin Erenkrantz
committed
mod_cache: Implement remove URL via a filter.
Remove entities from the cache when re-validation receives a 404 or other content-no-longer-present error. Suggested by: Paul Querna, Justin Erenkrantz Submitted by: Rudiger Plum <ruediger.pluem vodafone.com> Reviewed by: Justin Erenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@231487 13f79535-47bb-0310-9956-ffa450edef68
1 parent 72654c8 commit ab13cb3

5 files changed

Lines changed: 105 additions & 19 deletions

File tree

CHANGES

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
-*- coding: utf-8 -*-
22
Changes with Apache 2.3.0
33

4+
*) mod_cache: Remove entities from the cache when re-validation
5+
receives a 404 or other content-no-longer-present error.
6+
[Rüdiger Plüm ruediger.pluem vodafone.com]
7+
48
*) mod_disk_cache: Properly remove files from cache when needed.
59
[Rüdiger Plüm ruediger.pluem vodafone.com]
610

modules/cache/cache_storage.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,28 @@ extern module AP_MODULE_DECLARE_DATA cache_module;
2828
* delete all URL entities from the cache
2929
*
3030
*/
31-
int cache_remove_url(request_rec *r, char *url)
31+
int cache_remove_url(cache_request_rec *cache, apr_pool_t *p)
3232
{
3333
cache_provider_list *list;
3434
apr_status_t rv;
35-
char *key;
36-
cache_request_rec *cache = (cache_request_rec *)
37-
ap_get_module_config(r->request_config, &cache_module);
35+
cache_handle_t *h;
3836

39-
rv = cache_generate_key(r,r->pool,&key);
40-
if (rv != APR_SUCCESS) {
41-
return rv;
42-
}
37+
char *key;
4338

4439
list = cache->providers;
4540

41+
/* Remove the stale cache entry if present. If not, we're
42+
* being called from outside of a request; remove the
43+
* non-stalle handle.
44+
*/
45+
h = cache->stale_handle ? cache->stale_handle : cache->handle;
46+
if (!h) {
47+
return OK;
48+
}
49+
4650
/* for each specified cache type, delete the URL */
4751
while(list) {
48-
list->provider->remove_url(key);
52+
list->provider->remove_url(h, p);
4953
list = list->next;
5054
}
5155
return OK;

modules/cache/mod_cache.c

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ APR_OPTIONAL_FN_TYPE(ap_cache_generate_key) *cache_generate_key;
2929
*/
3030
static ap_filter_rec_t *cache_save_filter_handle;
3131
static ap_filter_rec_t *cache_out_filter_handle;
32+
static ap_filter_rec_t *cache_remove_url_filter_handle;
3233

3334
/*
3435
* CACHE handler
@@ -123,6 +124,19 @@ static int cache_url_handler(request_rec *r, int lookup)
123124
/* add cache_save filter to cache this request */
124125
ap_add_output_filter_handle(cache_save_filter_handle, NULL, r,
125126
r->connection);
127+
128+
ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
129+
"Adding CACHE_REMOVE_URL filter.");
130+
131+
/* Add cache_remove_url filter to this request to remove a
132+
* stale cache entry if needed. Also put the current cache
133+
* request rec in the filter context, as the request that
134+
* is available later during running the filter maybe
135+
* different due to an internal redirect.
136+
*/
137+
cache->remove_url_filter =
138+
ap_add_output_filter_handle(cache_remove_url_filter_handle,
139+
cache, r, r->connection);
126140
}
127141
else if (cache->stale_headers) {
128142
ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server,
@@ -441,11 +455,6 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
441455
if (reason) {
442456
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
443457
"cache: %s not cached. Reason: %s", url, reason);
444-
/* remove this object from the cache
445-
* BillS Asks.. Why do we need to make this call to remove_url?
446-
* leave it in for now..
447-
*/
448-
cache_remove_url(r, url);
449458

450459
/* remove this filter from the chain */
451460
ap_remove_output_filter(f);
@@ -546,6 +555,13 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
546555
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
547556
"cache: Caching url: %s", url);
548557

558+
/* We are actually caching this response. So it does not
559+
* make sense to remove this entity any more.
560+
*/
561+
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
562+
"cache: Removing CACHE_REMOVE_URL filter.");
563+
ap_remove_output_filter(cache->remove_url_filter);
564+
549565
/*
550566
* We now want to update the cache file header information with
551567
* the new date, last modified, expire and content length and write
@@ -714,6 +730,57 @@ static int cache_save_filter(ap_filter_t *f, apr_bucket_brigade *in)
714730
return ap_pass_brigade(f->next, in);
715731
}
716732

733+
/*
734+
* CACHE_REMOVE_URL filter
735+
* ---------------
736+
*
737+
* This filter gets added in the quick handler every time the CACHE_SAVE filter
738+
* gets inserted. Its purpose is to remove a confirmed stale cache entry from
739+
* the cache.
740+
*
741+
* CACHE_REMOVE_URL has to be a protocol filter to ensure that is run even if
742+
* the response is a canned error message, which removes the content filters
743+
* and thus the CACHE_SAVE filter from the chain.
744+
*
745+
* CACHE_REMOVE_URL expects cache request rec within its context because the
746+
* request this filter runs on can be different from the one whose cache entry
747+
* should be removed, due to internal redirects.
748+
*
749+
* Note that CACHE_SAVE_URL (as a content-set filter, hence run before the
750+
* protocol filters) will remove this filter if it decides to cache the file.
751+
* Therefore, if this filter is left in, it must mean we need to toss any
752+
* existing files.
753+
*/
754+
static int cache_remove_url_filter(ap_filter_t *f, apr_bucket_brigade *in)
755+
{
756+
request_rec *r = f->r;
757+
cache_request_rec *cache;
758+
759+
/* Setup cache_request_rec */
760+
cache = (cache_request_rec *) f->ctx;
761+
762+
if (!cache) {
763+
/* user likely configured CACHE_REMOVE_URL manually; they should really
764+
* use mod_cache configuration to do that. So:
765+
* 1. Remove ourselves
766+
* 2. Do nothing and bail out
767+
*/
768+
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
769+
"cache: CACHE_REMOVE_URL enabled unexpectedly");
770+
ap_remove_output_filter(f);
771+
return ap_pass_brigade(f->next, in);
772+
}
773+
/*
774+
* Now remove this cache entry from the cache
775+
*/
776+
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
777+
"cache: Removing url %s from the cache", f->r->unparsed_uri);
778+
cache_remove_url(cache, r->pool);
779+
/* remove ourselves */
780+
ap_remove_output_filter(f);
781+
return ap_pass_brigade(f->next, in);
782+
}
783+
717784
/* -------------------------------------------------------------- */
718785
/* Setup configurable data */
719786

@@ -967,6 +1034,7 @@ static int cache_post_config(apr_pool_t *p, apr_pool_t *plog,
9671034
return OK;
9681035
}
9691036

1037+
9701038
static const command_rec cache_cmds[] =
9711039
{
9721040
/* XXX
@@ -1033,6 +1101,15 @@ static void register_hooks(apr_pool_t *p)
10331101
cache_out_filter,
10341102
NULL,
10351103
AP_FTYPE_CONTENT_SET+1);
1104+
/* CACHE_REMOVE_URL has to be a protocol filter to ensure that is
1105+
* run even if the response is a canned error message, which
1106+
* removes the content filters.
1107+
*/
1108+
cache_remove_url_filter_handle =
1109+
ap_register_output_filter("CACHE_REMOVE_URL",
1110+
cache_remove_url_filter,
1111+
NULL,
1112+
AP_FTYPE_PROTOCOL);
10361113
ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
10371114
}
10381115

modules/cache/mod_cache.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ typedef struct {
197197
const char *urlkey, apr_off_t len);
198198
int (*open_entity) (cache_handle_t *h, request_rec *r,
199199
const char *urlkey);
200-
int (*remove_url) (const char *urlkey);
200+
int (*remove_url) (cache_handle_t *h, apr_pool_t *p);
201201
} cache_provider;
202202

203203
/* A linked-list of authn providers. */
@@ -225,6 +225,7 @@ typedef struct {
225225
apr_time_t exp; /* expiration */
226226
apr_time_t lastmod; /* last-modified time */
227227
cache_info *info; /* current cache info */
228+
ap_filter_t *remove_url_filter; /* Enable us to remove the filter */
228229
} cache_request_rec;
229230

230231

@@ -271,7 +272,7 @@ CACHE_DECLARE(apr_table_t *)ap_cache_cacheable_hdrs_out(apr_pool_t *pool,
271272
/**
272273
* cache_storage.c
273274
*/
274-
int cache_remove_url(request_rec *r, char *url);
275+
int cache_remove_url(cache_request_rec *cache, apr_pool_t *p);
275276
int cache_create_entity(request_rec *r, char *url, apr_off_t size);
276277
int cache_select_url(request_rec *r, char *url);
277278
apr_status_t cache_generate_key_default( request_rec *r, apr_pool_t*p, char**key );

modules/cache/mod_mem_cache.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,16 +601,16 @@ static int unserialize_table( cache_header_tbl_t *ctbl,
601601
/* remove_url()
602602
* Notes:
603603
*/
604-
static int remove_url(const char *key)
604+
static int remove_url(cache_handle_t *h, apr_pool_t *p)
605605
{
606606
cache_object_t *obj;
607607
int cleanup = 0;
608608

609609
if (sconf->lock) {
610610
apr_thread_mutex_lock(sconf->lock);
611611
}
612-
613-
obj = cache_find(sconf->cache_cache, key);
612+
613+
obj = h->cache_obj;
614614
if (obj) {
615615
cache_remove(sconf->cache_cache, obj);
616616
/* For performance, cleanup cache object after releasing the lock */

0 commit comments

Comments
 (0)