From: Brian Pane Date: Tue, 1 Jan 2002 20:36:18 +0000 (+0000) Subject: Generalized the recent prep_walk_cache optimizations to allow other X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc013bfad8dc09223fc2a5960cb4e7085f461e57;p=apache Generalized the recent prep_walk_cache optimizations to allow other modules to register "notes" within the array of working data in the core_request_config git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@92697 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/http_core.h b/include/http_core.h index 2c8bfb8525..7220f2d7cf 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -330,23 +330,53 @@ AP_DECLARE_DATA extern module core_module; /* Per-request configuration */ -typedef enum { - AP_WALK_DIRECTORY, - AP_WALK_LOCATION, - AP_WALK_FILE, - AP_NUM_WALK_CACHES -} ap_walk_cache_type; - typedef struct { /* bucket brigade used by getline for look-ahead and * ap_get_client_block for holding left-over request body */ struct apr_bucket_brigade *bb; - /* a place to hold per-request working data for - * ap_directory_walk, ap_location_walk, and ap_file_walk */ - void *walk_cache[AP_NUM_WALK_CACHES]; + /* an array of per-request working data elements, accessed + * by ID using ap_get_request_note() + * (Use ap_register_request_note() during initialization + * to add elements) + */ + void **notes; } core_request_config; +/* Standard entries that are guaranteed to be accessible via + * ap_get_request_note() for each request (additional entries + * can be added with ap_register_request_note()) + */ +#define AP_NOTE_DIRECTORY_WALK 0 +#define AP_NOTE_LOCATION_WALK 1 +#define AP_NOTE_FILE_WALK 2 +#define AP_NUM_STD_NOTES 3 + +/** + * Reserve an element in the core_request_config->notes array + * for some application-specific data + * @return An integer key that can be passed to ap_get_request_note() + * during request processing to access this element for the + * current request. + */ +AP_DECLARE(apr_size_t) ap_register_request_note(void); + +/** + * Retrieve a pointer to an element in the core_request_config->notes array + * @param r The request + * @param note_num A key for the element: either a value obtained from + * ap_register_request_note() or one of the predefined AP_NOTE_* + * values. + * @return NULL if the note_num is invalid, otherwise a pointer to the + * requested note element. + * @remark At the start of a request, each note element is NULL. The + * handle provided by ap_get_request_note() is a pointer-to-pointer + * so that the caller can point the element to some app-specific + * data structure. The caller should guarantee that any such + * structure will last as long as the request itself. + */ +AP_DECLARE(void **) ap_get_request_note(request_rec *r, apr_size_t note_num); + /* Per-directory configuration */ typedef unsigned char allow_options_t; diff --git a/server/core.c b/server/core.c index c3924d5d08..39ea6552db 100644 --- a/server/core.c +++ b/server/core.c @@ -62,6 +62,7 @@ #include "apr_fnmatch.h" #include "apr_hash.h" #include "apr_thread_proc.h" /* for RLIMIT stuff */ +#include "apr_hooks.h" #define APR_WANT_IOVEC #define APR_WANT_STRFUNC @@ -3383,11 +3384,44 @@ static void core_insert_filter(request_rec *r) } } +static apr_size_t num_request_notes = AP_NUM_STD_NOTES; + +static apr_status_t reset_request_notes(void *dummy) +{ + num_request_notes = AP_NUM_STD_NOTES; + return APR_SUCCESS; +} + +AP_DECLARE(apr_size_t) ap_register_request_note(void) +{ + apr_pool_cleanup_register(apr_global_hook_pool, NULL, reset_request_notes, + apr_pool_cleanup_null); + return num_request_notes++; +} + +AP_DECLARE(void **) ap_get_request_note(request_rec *r, apr_size_t note_num) +{ + core_request_config *req_cfg; + if (note_num >= num_request_notes) { + return NULL; + } + req_cfg = (core_request_config *) + ap_get_module_config(r->request_config, &core_module); + if (!req_cfg) { + return NULL; + } + return &(req_cfg->notes[note_num]); +} + static int core_create_req(request_rec *r) { + /* Alloc the config struct and the array of request notes in + * a single block for efficiency + */ core_request_config *req_cfg; - req_cfg = apr_palloc(r->pool, sizeof(core_request_config)); - memset(req_cfg, 0, sizeof(*req_cfg)); + req_cfg = apr_pcalloc(r->pool, sizeof(core_request_config) + + sizeof(void *) * num_request_notes); + req_cfg->notes = (void **)((char *)req_cfg + sizeof(core_request_config)); if (r->main) { core_request_config *main_req_cfg = (core_request_config *) ap_get_module_config(r->main->request_config, &core_module); diff --git a/server/request.c b/server/request.c index dd35e88c19..381390878a 100644 --- a/server/request.c +++ b/server/request.c @@ -296,10 +296,10 @@ typedef struct walk_cache_t { apr_array_header_t *walked; /* The list of walk_walked_t results */ } walk_cache_t; -static walk_cache_t *prep_walk_cache(ap_walk_cache_type t, request_rec *r) +static walk_cache_t *prep_walk_cache(apr_size_t t, request_rec *r) { walk_cache_t *cache; - core_request_config *my_req_cfg; + void **note; /* Find the most relevant, recent entry to work from. That would be * this request (on the second call), or the parent request of a @@ -307,20 +307,19 @@ static walk_cache_t *prep_walk_cache(ap_walk_cache_type t, request_rec *r) * this _walk()er with a copy it is allowed to munge. If there is no * parent or prior cached request, then create a new walk cache. */ - my_req_cfg = (core_request_config *) - ap_get_module_config(r->request_config, &core_module); - - if (!my_req_cfg || !(cache = my_req_cfg->walk_cache[t])) { - core_request_config *req_cfg; + note = ap_get_request_note(r, t); + if (!note) { + return NULL; + } + if (!(cache = *note)) { + void **inherit_note; if ((r->main && - (req_cfg = (core_request_config *) - ap_get_module_config(r->main->request_config, &core_module)) && - req_cfg->walk_cache[t]) || + ((inherit_note = ap_get_request_note(r->main, t))) && + *inherit_note) || (r->prev && - (req_cfg = (core_request_config *) - ap_get_module_config(r->prev->request_config, &core_module)) && - req_cfg->walk_cache[t])) { - cache = apr_pmemdup(r->pool, req_cfg->walk_cache[t], + ((inherit_note = ap_get_request_note(r->prev, t))) && + *inherit_note)) { + cache = apr_pmemdup(r->pool, *inherit_note, sizeof(*cache)); cache->walked = apr_array_copy(r->pool, cache->walked); } @@ -328,9 +327,7 @@ static walk_cache_t *prep_walk_cache(ap_walk_cache_type t, request_rec *r) cache = apr_pcalloc(r->pool, sizeof(*cache)); cache->walked = apr_array_make(r->pool, 4, sizeof(walk_walked_t)); } - if (my_req_cfg) { - my_req_cfg->walk_cache[t] = cache; - } + *note = cache; } return cache; } @@ -489,7 +486,7 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) */ r->filename = entry_dir; - cache = prep_walk_cache(AP_WALK_DIRECTORY, r); + cache = prep_walk_cache(AP_NOTE_DIRECTORY_WALK, r); /* If this is not a dirent subrequest with a preconstructed * r->finfo value, then we can simply stat the filename to @@ -1063,7 +1060,7 @@ AP_DECLARE(int) ap_location_walk(request_rec *r) walk_cache_t *cache; const char *entry_uri; - cache = prep_walk_cache(AP_WALK_LOCATION, r); + cache = prep_walk_cache(AP_NOTE_LOCATION_WALK, r); /* No tricks here, there are no to parse in this vhost. * We won't destroy the cache, just in case _this_ redirect is later @@ -1219,7 +1216,7 @@ AP_DECLARE(int) ap_file_walk(request_rec *r) return OK; } - cache = prep_walk_cache(AP_WALK_FILE, r); + cache = prep_walk_cache(AP_NOTE_FILE_WALK, r); /* No tricks here, there are just no to parse in this context. * We won't destroy the cache, just in case _this_ redirect is later