httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ruediger Pluem <rpl...@apache.org>
Subject 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
Date Sat, 03 Oct 2009 08:57:40 GMT


On 10/03/2009 01:47 AM, minfrin@apache.org 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

Mime
View raw message