Return-Path: Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 36871 invoked by uid 500); 27 Aug 2001 04:29:13 -0000 Delivered-To: apmail-httpd-2.0-cvs@apache.org Received: (qmail 36868 invoked from network); 27 Aug 2001 04:29:13 -0000 Received: from icarus.apache.org (64.125.133.21) by daedalus.apache.org with SMTP; 27 Aug 2001 04:29:13 -0000 Received: (qmail 43546 invoked by uid 1134); 27 Aug 2001 04:29:09 -0000 Date: 27 Aug 2001 04:29:09 -0000 Message-ID: <20010827042909.43545.qmail@icarus.apache.org> From: wrowe@apache.org To: httpd-2.0-cvs@apache.org Subject: cvs commit: httpd-2.0/server request.c X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N Status: O X-Status: X-Keywords: X-UID: 545 wrowe 01/08/26 21:29:09 Modified: . CHANGES server request.c Log: Clean up location_walk, so that this step performs a minimum amount of redundant effort (it must be run twice, but it will no longer reparse all blocks when the request uri hadn't changed.) The location walk block is refactored, with some significant changes in variable names for legibility. Cooler still, it uses pool data instead of 'notes' for the important cache info :) Note the patch builds the per dir config from _nothing_, and then merges it into the per_dir_config. When the underlying per_dir_config changes between passes, the location_walk can simply tack back on this preconstruct onto the new per_dir_config. Revision Changes Path 1.332 +5 -0 httpd-2.0/CHANGES Index: CHANGES =================================================================== RCS file: /home/cvs/httpd-2.0/CHANGES,v retrieving revision 1.331 retrieving revision 1.332 diff -u -r1.331 -r1.332 --- CHANGES 2001/08/26 05:10:16 1.331 +++ CHANGES 2001/08/27 04:29:09 1.332 @@ -1,5 +1,10 @@ Changes with Apache 2.0.25-dev + *) Clean up location_walk, so that this step performs a minimum + amount of redundant effort (it must be run twice, but it will no + longer reparse all blocks when the request uri + hadn't changed.) [William Rowe] + *) Eliminate proxy: (and all other 'special') processing from the ap_directory_walk() phase. Modules that want to use special walk logic should refer to the mod_proxy map_to_location example, 1.33 +96 -47 httpd-2.0/server/request.c Index: request.c =================================================================== RCS file: /home/cvs/httpd-2.0/server/request.c,v retrieving revision 1.32 retrieving revision 1.33 diff -u -r1.32 -r1.33 --- request.c 2001/08/26 05:10:17 1.32 +++ request.c 2001/08/27 04:29:09 1.33 @@ -963,68 +963,117 @@ core_server_config *sconf = ap_get_module_config(r->server->module_config, &core_module); ap_conf_vector_t *per_dir_defaults = r->per_dir_config; - ap_conf_vector_t **url = (ap_conf_vector_t **) sconf->sec_url->elts; - int len, num_url = sconf->sec_url->nelts; + 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; core_dir_config *entry_core; - char *entry_url; + char *entry_uri; int j; - if (!num_url) { + /* No tricks here, there are no to parse in this vhost + */ + 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(&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 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 (r->uri[0] != '/') { - test_location = r->uri; + 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 (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. + */ + for (j = 0; j < num_loc; ++j) { + + entry_config = locations[j]; + + entry_core = ap_get_module_config(entry_config, &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 pattern was + * not slash terminated, then this uri must be slash + * terminated (or at the end of the string) to match. + */ + 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) + || (entry_uri[len - 1] != '/' + && test_location[len] != '/' + && test_location[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; + } + + /* 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 { - test_location = apr_pstrdup(r->pool, r->uri); - ap_no2slash(test_location); + /* Well this looks familiar! Get back our per_uri_defaults + * from the last location walk. + */ + apr_pool_userdata_get(&per_uri_defaults, "ap_location_walk::dir_conf", + r->pool); } - /* 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. + /* We might be able to optimize further, if r->per_dir_config never changed. + * In any case, merge our per_uri_defaults onto */ - for (j = 0; j < num_url; ++j) { - - entry_config = url[j]; - - entry_core = ap_get_module_config(entry_config, &core_module); - entry_url = entry_core->d; - - len = strlen(entry_url); - - this_conf = NULL; - - if (entry_core->r) { - if (!ap_regexec(entry_core->r, r->uri, 0, NULL, 0)) - this_conf = entry_config; - } - else if (entry_core->d_is_fnmatch) { - if (!apr_fnmatch(entry_url, test_location, FNM_PATHNAME)) { - this_conf = entry_config; - } - } - else if (!strncmp(test_location, entry_url, len) && - (entry_url[len - 1] == '/' || - test_location[len] == '/' || test_location[len] == '\0')) - this_conf = entry_config; - - if (this_conf) - per_dir_defaults = ap_merge_per_dir_configs(r->pool, - per_dir_defaults, - this_conf); - } - r->per_dir_config = per_dir_defaults; + if (per_uri_defaults) + r->per_dir_config = ap_merge_per_dir_configs(r->pool, + r->per_dir_config, + per_uri_defaults); return OK; }