
rpluem at apache
Oct 3, 2009, 1:57 AM
Post #1 of 4
(237 views)
Permalink
|
|
Re: svn commit: r821202 - in /httpd/httpd/trunk: CHANGES docs/manual/mod/mod_cache.xml modules/cache/mod_cache.c modules/cache/mod_cache.h
|
|
On 10/03/2009 01:47 AM, minfrin [at] apache wrote: > Author: minfrin > Date: Fri Oct 2 23:47:37 2009 > New Revision: 821202 > > URL: http://svn.apache.org/viewvc?rev=821202&view=rev > Log: > mod_cache: Introduce the option to run the cache from within the > normal request handler, and to allow fine grained control over > where in the filter chain content is cached. > > Modified: > httpd/httpd/trunk/CHANGES > httpd/httpd/trunk/docs/manual/mod/mod_cache.xml > httpd/httpd/trunk/modules/cache/mod_cache.c > httpd/httpd/trunk/modules/cache/mod_cache.h > Modified: httpd/httpd/trunk/modules/cache/mod_cache.c > URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_cache.c?rev=821202&r1=821201&r2=821202&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/cache/mod_cache.c (original) > +++ httpd/httpd/trunk/modules/cache/mod_cache.c Fri Oct 2 23:47:37 2009 > @@ -271,6 +290,245 @@ > return OK; > } > > +/** > + * If the two filter handles are present within the filter chain, replace > + * the last instance of the first filter with the last instance of the > + * second filter, and return true. If the second filter is not present at > + * all, the first filter is removed, and false is returned. If neither > + * filter is present, false is returned and this function does nothing. > + */ > +static int cache_replace_filter(ap_filter_t *next, ap_filter_rec_t *from, > + ap_filter_rec_t *to) { > + ap_filter_t *ffrom = NULL, *fto = NULL; > + while (next) { > + if (next->frec == from && !next->ctx) { > + ffrom = next; > + } > + if (next->frec == to && !next->ctx) { > + fto = next; > + } > + next = next->next; > + } > + if (ffrom && fto) { > + ffrom->frec = fto->frec; > + ffrom->ctx = fto->ctx; > + ap_remove_output_filter(fto); > + return 1; > + } > + if (fto) { > + ap_remove_output_filter(fto); > + } > + return 0; > +} > + > +/** > + * The cache handler is functionally similar to the cache_quick_hander, > + * however a number of steps that are required by the quick handler are > + * not required here, as the normal httpd processing has already handled > + * these steps. > + */ > +static int cache_handler(request_rec *r) > +{ > + apr_status_t rv; > + const char *auth; > + cache_provider_list *providers; > + cache_request_rec *cache; > + apr_bucket_brigade *out; > + ap_filter_t *next; > + ap_filter_rec_t *cache_out_handle; > + ap_filter_rec_t *cache_save_handle; > + cache_server_conf *conf; > + > + /* Delay initialization until we know we are handling a GET */ > + if (r->method_number != M_GET) { > + return DECLINED; > + } > + > + conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, > + &cache_module); > + > + /* only run if the quick handler is disabled */ > + if (conf->quick) { > + return DECLINED; > + } > + > + /* > + * Which cache module (if any) should handle this request? > + */ > + if (!(providers = ap_cache_get_providers(r, conf, r->parsed_uri))) { > + return DECLINED; > + } > + > + /* make space for the per request config */ > + cache = (cache_request_rec *) ap_get_module_config(r->request_config, > + &cache_module); > + if (!cache) { > + cache = apr_pcalloc(r->pool, sizeof(cache_request_rec)); > + ap_set_module_config(r->request_config, &cache_module, cache); > + } > + > + /* save away the possible providers */ > + cache->providers = providers; > + > + /* > + * Try to serve this request from the cache. > + * > + * If no existing cache file (DECLINED) > + * add cache_save filter > + * If cached file (OK) > + * clear filter stack > + * add cache_out filter > + * return OK > + */ > + rv = cache_select(r); > + if (rv != OK) { > + if (rv == DECLINED) { > + > + /* try to obtain a cache lock at this point. if we succeed, > + * we are the first to try and cache this url. if we fail, > + * it means someone else is already trying to cache this > + * url, and we should just let the request through to the > + * backend without any attempt to cache. this stops > + * duplicated simultaneous attempts to cache an entity. > + */ > + rv = ap_cache_try_lock(conf, r, NULL); > + if (APR_SUCCESS == rv) { > + > + /* > + * Add cache_save filter to cache this request. Choose > + * the correct filter by checking if we are a subrequest > + * or not. > + */ > + if (r->main) { > + ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, > + r->server, > + "Adding CACHE_SAVE_SUBREQ filter for %s", > + r->uri); > + cache_save_handle = cache_save_subreq_filter_handle; > + } > + else { > + ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, > + r->server, "Adding CACHE_SAVE filter for %s", > + r->uri); > + cache_save_handle = cache_save_filter_handle; > + } > + ap_add_output_filter_handle(cache_save_handle, > + NULL, r, r->connection); > + > + /* > + * Did the user indicate the precise location of the > + * CACHE_SAVE filter by inserting the CACHE filter as a > + * marker? > + * > + * If so, we get cunning and replace CACHE with the > + * CACHE_SAVE filter. This has the effect of inserting > + * the CACHE_SAVE filter at the precise location where > + * the admin wants to cache the content. All filters that > + * lie before and after the original location of the CACHE > + * filter will remain in place. > + */ > + if (cache_replace_filter(r->output_filters, > + cache_filter_handle, cache_save_handle)) { > + ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, > + r->server, "Replacing CACHE with CACHE_SAVE " > + "filter for %s", r->uri); > + } > + > + ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server, > + "Adding CACHE_REMOVE_URL filter for %s", > + r->uri); > + > + /* Add cache_remove_url filter to this request to remove a > + * stale cache entry if needed. Also put the current cache > + * request rec in the filter context, as the request that > + * is available later during running the filter may be > + * different due to an internal redirect. > + */ > + cache->remove_url_filter = > + ap_add_output_filter_handle(cache_remove_url_filter_handle, > + cache, r, r->connection); > + > + } > + else { > + ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, > + r->server, "Cache locked for url, not caching " > + "response: %s", r->uri); > + } > + } > + else { > + /* error */ > + ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, > + "cache: error returned while checking for cached " > + "file by %s cache", cache->provider_name); > + } > + return DECLINED; > + } Hm, why don't we do the ap_meets_conditions test here like in the quick handler rv = ap_meets_conditions(r); if (rv != OK) { /* Return cached status. */ return rv; } > + > + /* Serve up the content */ > + > + /* > + * Add cache_out filter to serve this request. Choose > + * the correct filter by checking if we are a subrequest > + * or not. > + */ > + if (r->main) { > + cache_out_handle = cache_out_subreq_filter_handle; > + } > + else { > + cache_out_handle = cache_out_filter_handle; > + } > + ap_add_output_filter_handle(cache_out_handle, NULL, r, r->connection); > + Plus we have one new warning: mod_cache.c: In function 'cache_handler': mod_cache.c:333: warning: unused variable 'auth' Regards Rüdiger
|