httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wr...@apache.org
Subject cvs commit: httpd-2.0/server request.c
Date Thu, 06 Sep 2001 16:48:16 GMT
wrowe       01/09/06 09:48:16

  Modified:    server   request.c
  Log:
    Optimize location_walk.  We build an array of incremental matches, and
    on attempting a subreq/redirect or simply a second pass, and for each
    match in series, if the section is a match,  we reuse the merge result
    for that section.
  
  Revision  Changes    Path
  1.49      +126 -86   httpd-2.0/server/request.c
  
  Index: request.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/server/request.c,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- request.c	2001/09/01 05:21:16	1.48
  +++ request.c	2001/09/06 16:48:15	1.49
  @@ -1082,21 +1082,57 @@
   
   #endif /* defined REPLACE_PATH_INFO_METHOD */
   
  +typedef struct walk_walked_t {
  +    ap_conf_vector_t *matched; /* A dir_conf sections we matched */
  +    ap_conf_vector_t *merged;  /* The dir_conf merged result */
  +} walk_walked_t;
  +
  +typedef struct walk_cache_t {
  +    const char         *cached;         /* The identifier we matched */
  +    ap_conf_vector_t  **dir_conf_tested;/* The sections we matched against */
  +    ap_conf_vector_t   *per_dir_result; /* per_dir_config += walked result */
  +    apr_array_header_t *walked;         /* The list of walk_walked_t results */
  +} walk_cache_t;
   
   AP_DECLARE(int) ap_location_walk(request_rec *r)
   {
  +    ap_conf_vector_t *now_merged = NULL;
       core_server_config *sconf = ap_get_module_config(r->server->module_config,
                                                        &core_module);
  -    ap_conf_vector_t *per_uri_defaults = NULL;
       ap_conf_vector_t **locations = (ap_conf_vector_t **) sconf->sec_url->elts;
  -    ap_conf_vector_t **loc_done = NULL;
  -    int len, num_loc = sconf->sec_url->nelts;
  -    char *test_location;
  -    ap_conf_vector_t *this_conf;
  -    ap_conf_vector_t *entry_config;
  +    int num_loc = sconf->sec_url->nelts;
       core_dir_config *entry_core;
  -    char *entry_uri;
  -    int j;
  +    walk_cache_t *cache;
  +    walk_walked_t *last_walk;
  +    const char *entry_uri;
  +    int len, j;
  +
  +    /* Find the most relevant, recent entry to work from.  That would be
  +     * this request (on the second call), or the parent request of a
  +     * subrequest, or the prior request of an internal redirect.
  +     */
  +    if ((apr_pool_userdata_get((void **)&cache, 
  +                               "ap_location_walk::cache", r->pool)
  +                != APR_SUCCESS) || !cache) 
  +    {
  +        if ((r->main && (apr_pool_userdata_get((void **)&cache, 
  +                                               "ap_location_walk::cache",
  +                                               r->main->pool)
  +                                 == APR_SUCCESS) && cache)
  +         || (r->prev && (apr_pool_userdata_get((void **)&cache, 
  +                                               "ap_location_walk::cache",
  +                                               r->prev->pool)
  +                                 == APR_SUCCESS) && cache)) {
  +            cache = apr_pmemdup(r->pool, cache, sizeof(*cache));
  +            cache->walked = apr_array_copy(r->pool, cache->walked);
  +        }
  +        else {
  +            cache = apr_pcalloc(r->pool, sizeof(*cache));
  +            cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t));
  +        }
  +        apr_pool_userdata_set(cache, "ap_location_walk::cache", 
  +                              apr_pool_cleanup_null, r->pool);
  +    }
   
       /* If the initial request creation logic failed to reset the
        * per_dir_config, we will do so here.
  @@ -1105,58 +1141,65 @@
       if (!r->per_dir_config)
           r->per_dir_config = r->server->lookup_defaults;
       
  -
  -    /* No tricks here, there are no <Locations > to parse in this vhost
  +    /* No tricks here, there are no <Locations > to parse in this vhost.
  +     * We cache NULL because it's possible that another vhost had some
  +     * different locations, and we are throwing those away.
        */
       if (!num_loc) {
  -        apr_pool_userdata_set(NULL, "ap_location_walk::dir_conf", 
  -                              apr_pool_cleanup_null, r->pool);
  -        apr_pool_userdata_set(NULL, "ap_location_walk::loc_done", 
  -                              apr_pool_cleanup_null, r->pool);
  -        apr_pool_userdata_set(NULL, "ap_location_walk::last_uri",
  -                              apr_pool_cleanup_null, r->pool);
   	return OK;
       }
   
  -    apr_pool_userdata_get((void **)&entry_uri, "ap_location_walk::last_uri", r->pool);
  -    apr_pool_userdata_get((void **)&loc_done, "ap_location_walk::loc_done", r->pool);
  +    /* Location and LocationMatch differ on their behaviour w.r.t. multiple
  +     * slashes.  Location matches multiple slashes with a single slash,
  +     * LocationMatch doesn't.  An exception, for backwards brokenness is
  +     * absoluteURIs... in which case neither match multiple slashes.
  +     */
  +    if (r->uri[0] != '/') {
  +	entry_uri = r->uri;
  +    }
  +    else {
  +        char *uri = apr_pstrdup(r->pool, r->uri);
  +	ap_no2slash(uri);
  +        entry_uri = uri;
  +    }
   
  -    /* If we have an ap_location_walk::last_uri that matches r->uri,
  -     * and the vhost's list of locations hasn't changed,
  -     * we will go through the location_walk entries.
  +    /* If we have an cache->cached location that matches r->uri,
  +     * and the vhost's list of locations hasn't changed, we can skip
  +     * rewalking the location_walk entries.
        */
  -    if (!entry_uri || (loc_done != locations) 
  -                   || (strcmp(r->uri, entry_uri) != 0))
  -    {
  -        /* Location and LocationMatch differ on their behaviour w.r.t. multiple
  -         * slashes.  Location matches multiple slashes with a single slash,
  -         * LocationMatch doesn't.  An exception, for backwards brokenness is
  -         * absoluteURIs... in which case neither match multiple slashes.
  +    if (cache->cached && (cache->dir_conf_tested == locations) 
  +                      && (strcmp(entry_uri, cache->cached) == 0)) {
  +        /* Well this looks really familiar!  If our end-result (per_dir_result)
  +         * didn't change, we have absolutely nothing to do :)  
  +         * Otherwise (as is the case with most dir_merged/file_merged requests)
  +         * we must merge our dir_conf_merged onto this new r->per_dir_config.
            */
  -        if (r->uri[0] != '/') {
  -	    test_location = r->uri;
  -        }
  -        else {
  -	    test_location = apr_pstrdup(r->pool, r->uri);
  -	    ap_no2slash(test_location);
  -        }
  -
  -        /* Go through the location entries, and check for matches. */
  -
  -        /* we apply the directive sections in some order;
  -         * should really try them with the most general first.
  +        if (cache->per_dir_result == r->per_dir_config)
  +            return OK;
  +        if (cache->walked->nelts)
  +            now_merged = ((walk_walked_t*)cache->walked->elts)
  +                                            [cache->walked->nelts - 1].merged;
  +    }
  +    else {
  +        /* We start now_merged from NULL since we want to build 
  +         * a locations list that can be merged to any vhost.
  +         */
  +        int matches = cache->walked->nelts;
  +        last_walk = (walk_walked_t*)cache->walked->elts;
  +        cache->cached = entry_uri;
  +        cache->dir_conf_tested = locations;
  +
  +        /* Go through the location entries, and check for matches.
  +         * We apply the directive sections in given order, we should
  +         * really try them with the most general first.
            */
           for (j = 0; j < num_loc; ++j) {
   
  -	    entry_config = locations[j];
  -
  -	    entry_core = ap_get_module_config(entry_config, &core_module);
  +	    entry_core = ap_get_module_config(locations[j], &core_module);
   	    entry_uri = entry_core->d;
   
   	    len = strlen(entry_uri);
   
  -	    this_conf = NULL;
  -            
               /* Test the regex, fnmatch or string as appropriate.
                * If it's a strcmp, and the <Location > pattern was 
                * not slash terminated, then this uri must be slash
  @@ -1165,60 +1208,57 @@
   	    if (entry_core->r 
                     ? ap_regexec(entry_core->r, r->uri, 0, NULL, 0)
                     : (entry_core->d_is_fnmatch
  -                       ? apr_fnmatch(entry_uri, test_location, FNM_PATHNAME)
  -                       : (strncmp(test_location, entry_uri, len)
  +                       ? apr_fnmatch(entry_uri, cache->cached, FNM_PATHNAME)
  +                       : (strncmp(cache->cached, entry_uri, len)
                               || (entry_uri[len - 1] != '/'
  -                             && test_location[len] != '/' 
  -                             && test_location[len] != '\0')))) {
  +                             && cache->cached[len] != '/' 
  +                             && cache->cached[len] != '\0')))) {
   	        continue;
               }
   
  -            if (per_uri_defaults)
  -	        per_uri_defaults = ap_merge_per_dir_configs(r->pool,
  -                                                            per_uri_defaults,
  -                                                            entry_config);
  -            else
  -                per_uri_defaults = entry_config;
  -        }
  +            /* If we merged this same section last time, reuse it
  +             */
  +            if (matches) {
  +                if (last_walk->matched == locations[j]) {
  +                    now_merged = last_walk->merged;
  +                    ++last_walk;
  +                    --matches;
  +                    continue;
  +                }
  +                /* We fell out of sync.  This is our own copy of walked,
  +                 * so truncate the remaining matches and reset remaining.
  +                 */
  +                cache->walked->nelts -= matches;
  +                matches = 0;
  +            }
   
  -        /* Set aside this walk result, in case we end up back here with
  -         * the same uri again.
  -         */
  -        apr_pool_userdata_set(per_uri_defaults, "ap_location_walk::dir_conf", 
  -                              apr_pool_cleanup_null, r->pool);
  -        apr_pool_userdata_set(locations, "ap_location_walk::loc_done", 
  -                              apr_pool_cleanup_null, r->pool);
  -        apr_pool_userdata_set(r->uri, "ap_location_walk::last_uri", 
  -                              apr_pool_cleanup_null, r->pool);
  -    }
  -    else {
  -        /* Well this looks familiar!  If our end-result (dir_merged) hasn't
  -         * changed, we have nothing to do :)  This test really doesn't play well
  -         * with other walkers who reset to the vhost default, but we will
  -         * leave this escape in for simpler modules.
  -         */
  -        apr_pool_userdata_get((void **)&per_uri_defaults, "ap_location_walk::dir_merged",
  -                              r->pool);
  -        if (per_uri_defaults == r->per_dir_config)
  -            return OK;
  +            if (now_merged)
  +	        now_merged = ap_merge_per_dir_configs(r->pool, 
  +                                                      now_merged,
  +                                                      locations[j]);
  +            else
  +                now_merged = locations[j];
   
  -        /* Well, we will need our per_uri_defaults from the last location walk. 
  -         * after all.
  +            last_walk = (walk_walked_t*)apr_array_push(cache->walked);
  +            last_walk->matched = locations[j];
  +            last_walk->merged = now_merged;
  +        }
  +        /* Whoops - everything matched in sequence, but the original walk
  +         * found some additional matches.  Truncate them.
            */
  -        apr_pool_userdata_get((void **)&per_uri_defaults, "ap_location_walk::dir_conf",
  -                              r->pool);
  +        if (matches)
  +            cache->walked->nelts -= matches;
       }
   
  -    /* Merge our per_uri_defaults preconstruct onto the r->per_dir_configs,
  -     * and note the end result for later optimization.
  +    /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
  +     * and note the end result to (potentially) skip this step next time.
        */
  -    if (per_uri_defaults)
  +    if (now_merged)
           r->per_dir_config = ap_merge_per_dir_configs(r->pool,
                                                        r->per_dir_config,
  -                                                     per_uri_defaults);
  +                                                     now_merged);
  +    cache->per_dir_result = r->per_dir_config;
   
  -    apr_pool_userdata_set(r->per_dir_config, "ap_location_walk::dir_merged", 
  -                          apr_pool_cleanup_null, r->pool);
       return OK;
   }
   
  
  
  

Mime
View raw message