Return-Path: Delivered-To: apmail-modperl-cvs-archive@apache.org Received: (qmail 38485 invoked by uid 500); 17 Mar 2001 06:03:38 -0000 Mailing-List: contact modperl-cvs-help@apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: dev@perl.apache.org Delivered-To: mailing list modperl-cvs@apache.org Received: (qmail 38474 invoked by uid 500); 17 Mar 2001 06:03:38 -0000 Delivered-To: apmail-modperl-2.0-cvs@apache.org Date: 17 Mar 2001 06:03:38 -0000 Message-ID: <20010317060338.38470.qmail@apache.org> From: dougm@apache.org To: modperl-2.0-cvs@apache.org Subject: cvs commit: modperl-2.0/xs/maps apache_functions.map dougm 01/03/16 22:03:38 Modified: lib/ModPerl Code.pm src/modules/perl modperl_callback.c modperl_config.h modperl_handler.c modperl_handler.h modperl_mgv.c modperl_mgv.h xs/Apache/RequestUtil Apache__RequestUtil.h xs/maps apache_functions.map Added: xs/Apache/ServerUtil Apache__ServerUtil.h Log: implement ${r,s}->{push,set,get}_handlers} Revision Changes Path 1.51 +1 -1 modperl-2.0/lib/ModPerl/Code.pm Index: Code.pm =================================================================== RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- Code.pm 2001/03/16 07:30:21 1.50 +++ Code.pm 2001/03/17 06:03:37 1.51 @@ -92,7 +92,7 @@ Srv => [qw(NONE CLONE PARENT ENABLED AUTOLOAD), @hook_flags, 'UNSET'], Dir => [qw(NONE SEND_HEADER SETUP_ENV UNSET)], Interp => [qw(NONE IN_USE PUTBACK CLONED BASE)], - Handler => [qw(NONE PARSED METHOD OBJECT ANON AUTOLOAD)], + Handler => [qw(NONE PARSED METHOD OBJECT ANON AUTOLOAD DYNAMIC)], ); my %flags_lookup = map { $_,1 } qw(Srv Dir); 1.36 +4 -2 modperl-2.0/src/modules/perl/modperl_callback.c Index: modperl_callback.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_callback.c,v retrieving revision 1.35 retrieving revision 1.36 diff -u -r1.35 -r1.36 --- modperl_callback.c 2001/03/16 17:23:23 1.35 +++ modperl_callback.c 2001/03/17 06:03:37 1.36 @@ -9,7 +9,7 @@ int count, status; #ifdef USE_ITHREADS - if (p && !MpHandlerPARSED(handler)) { + if (p && !MpHandlerPARSED(handler) && !MpHandlerDYNAMIC(handler)) { MP_dSCFG(s); if (scfg->threaded_mpm) { /* @@ -103,6 +103,7 @@ #endif MP_dSCFG(s); MP_dDCFG; + MP_dRCFG; modperl_handler_t **handlers; apr_pool_t *p = NULL; MpAV *av, **avp; @@ -123,7 +124,7 @@ p = pconf; } - avp = modperl_handler_lookup_handlers(dcfg, scfg, NULL, p, + avp = modperl_handler_lookup_handlers(dcfg, scfg, rcfg, p, type, idx, FALSE, &desc); if (!(avp && (av = *avp))) { @@ -171,6 +172,7 @@ break; }; + /* XXX: deal with {push,set}_handler of the phase we're currently in */ MP_TRACE_h(MP_FUNC, "running %d %s handlers\n", av->nelts, desc); handlers = (modperl_handler_t **)av->elts; 1.24 +4 -0 modperl-2.0/src/modules/perl/modperl_config.h Index: modperl_config.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_config.h,v retrieving revision 1.23 retrieving revision 1.24 diff -u -r1.23 -r1.24 --- modperl_config.h 2001/03/16 06:35:18 1.23 +++ modperl_config.h 2001/03/17 06:03:37 1.24 @@ -37,6 +37,10 @@ (r ? (modperl_config_dir_t *) \ ap_get_module_config(r->per_dir_config, &perl_module) : NULL) +#define modperl_config_dir_get_defaults(s) \ + (modperl_config_dir_t *) \ + ap_get_module_config(s->lookup_defaults, &perl_module) + #define MP_dDCFG \ modperl_config_dir_t *dcfg = modperl_config_dir_get(r) 1.6 +216 -5 modperl-2.0/src/modules/perl/modperl_handler.c Index: modperl_handler.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_handler.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- modperl_handler.c 2001/03/16 17:23:24 1.5 +++ modperl_handler.c 2001/03/17 06:03:37 1.6 @@ -64,41 +64,252 @@ #define set_desc(dtype) \ MP_TRACE_a_do(if (desc) *desc = modperl_handler_desc_##dtype(idx)) +#define check_modify(dtype) \ +if ((action > MP_HANDLER_ACTION_GET) && rcfg) { \ + dTHX; \ + Perl_croak(aTHX_ "too late to modify %s handlers", \ + modperl_handler_desc_##dtype(idx)); \ +} + +/* + * generic function to lookup handlers for use in modperl_callback(), + * $r->{push,set,get}_handlers, $s->{push,set,get}_handlers + * $s->push/set at startup time are the same as configuring Perl*Handlers + * $r->push/set at request time will create entries in r->request_config + * push will first merge with configured handlers, unless an entry + * in r->request_config already exists. in this case, push or set has + * already been called for the given handler, + * r->request_config entries then override those in r->per_dir_config + */ + MpAV **modperl_handler_lookup_handlers(modperl_config_dir_t *dcfg, modperl_config_srv_t *scfg, modperl_config_req_t *rcfg, apr_pool_t *p, - int type, int idx, int lvalue, + int type, int idx, + modperl_handler_action_e action, const char **desc) { - MpAV **avp = NULL; + MpAV **avp = NULL, **ravp = NULL; switch (type) { case MP_HANDLER_TYPE_PER_DIR: avp = &dcfg->handlers_per_dir[idx]; + if (rcfg) { + ravp = &rcfg->handlers_per_dir[idx]; + } set_desc(per_dir); break; case MP_HANDLER_TYPE_PER_SRV: avp = &scfg->handlers_per_srv[idx]; + if (rcfg) { + ravp = &rcfg->handlers_per_srv[idx]; + } set_desc(per_srv); break; case MP_HANDLER_TYPE_CONNECTION: avp = &scfg->handlers_connection[idx]; + check_modify(connection); set_desc(connection); break; case MP_HANDLER_TYPE_FILES: avp = &scfg->handlers_files[idx]; + check_modify(files); set_desc(files); break; case MP_HANDLER_TYPE_PROCESS: avp = &scfg->handlers_process[idx]; + check_modify(files); set_desc(process); break; }; + + if (!avp) { + /* should never happen */ + fprintf(stderr, "PANIC: no such handler type: %d\n", type); + return NULL; + } + + switch (action) { + case MP_HANDLER_ACTION_GET: + /* just a lookup */ + break; + case MP_HANDLER_ACTION_PUSH: + if (ravp && !*ravp) { + if (*avp) { + /* merge with existing configured handlers */ + *ravp = apr_array_copy(p, *avp); + } + else { + /* no request handlers have been previously pushed or set */ + *ravp = modperl_handler_array_new(p); + } + } + else if (!*avp) { + /* directly modify the configuration at startup time */ + *avp = modperl_handler_array_new(p); + } + break; + case MP_HANDLER_ACTION_SET: + if (ravp) { + if (*ravp) { + /* wipe out existing pushed/set request handlers */ + (*ravp)->nelts = 0; + } + else { + /* no request handlers have been previously pushed or set */ + *ravp = modperl_handler_array_new(p); + } + } + else if (*avp) { + /* wipe out existing configuration, only at startup time */ + (*avp)->nelts = 0; + } + else { + /* no configured handlers for this phase */ + *avp = modperl_handler_array_new(p); + } + break; + } + + return (ravp && *ravp) ? ravp : avp; +} + +MpAV **modperl_handler_get_handlers(request_rec *r, conn_rec *c, server_rec *s, + apr_pool_t *p, const char *name, + modperl_handler_action_e action) +{ + MP_dSCFG(s); + MP_dDCFG; + MP_dRCFG; + + int idx, type; + + if (!r) { + /* so $s->{push,set}_handlers can configured request-time handlers */ + dcfg = modperl_config_dir_get_defaults(s); + } + + if ((idx = modperl_handler_lookup(name, &type)) == DECLINED) { + return FALSE; + } + + if (r) { + modperl_config_req_init(r, rcfg); + } + + return modperl_handler_lookup_handlers(dcfg, scfg, rcfg, p, + type, idx, + action, NULL); +} + +int modperl_handler_push_handlers(pTHX_ apr_pool_t *p, + MpAV *handlers, SV *sv) +{ + char *handler_name; + + if ((handler_name = modperl_mgv_name_from_sv(aTHX_ p, sv))) { + modperl_handler_t *handler = + modperl_handler_new(p, apr_pstrdup(p, handler_name)); + modperl_handler_array_push(handlers, handler); + return TRUE; + } - if (lvalue && avp && !*avp && p) { - *avp = apr_array_make(p, lvalue, sizeof(modperl_handler_t *)); + MP_TRACE_h(MP_FUNC, "unable to push_handler 0x%lx\n", + (unsigned long)sv); + + return FALSE; +} + +/* convert array header of modperl_handlers_t's to AV ref of CV refs */ +SV *modperl_handler_perl_get_handlers(pTHX_ MpAV **handp, apr_pool_t *p) +{ + AV *av = newAV(); + int i; + modperl_handler_t **handlers; + + if (!(handp && *handp)) { + return &PL_sv_undef; + } + + av_extend(av, (*handp)->nelts - 1); + + handlers = (modperl_handler_t **)(*handp)->elts; + + for (i=0; i<(*handp)->nelts; i++) { + modperl_handler_t *handler = NULL; + GV *gv; + + if (MpHandlerPARSED(handlers[i])) { + handler = handlers[i]; + } + else { +#ifdef USE_ITHREADS + if (!MpHandlerDYNAMIC(handlers[i])) { + handler = modperl_handler_dup(p, handlers[i]); + } +#endif + if (!handler) { + handler = handlers[i]; + } + + if (!modperl_mgv_resolve(aTHX_ handler, p, handler->name)) { + MP_TRACE_h(MP_FUNC, "failed to resolve handler %s\n", + handler->name); + } + + } + + if (handler->mgv_cv) { + if ((gv = modperl_mgv_lookup(aTHX_ handler->mgv_cv))) { + CV *cv = modperl_mgv_cv(gv); + av_push(av, newRV_inc((SV*)cv)); + } + } + else { + av_push(av, newSVpv(handler->name, 0)); + } + } + + return newRV_noinc((SV*)av); +} + +#define push_sv_handler \ + if ((modperl_handler_push_handlers(aTHX_ p, *handlers, sv))) { \ + MpHandlerDYNAMIC_On(modperl_handler_array_last(*handlers)); \ + } + +/* allow push/set of single cv ref or array ref of cv refs */ +int modperl_handler_perl_add_handlers(pTHX_ + request_rec *r, + conn_rec *c, + server_rec *s, + apr_pool_t *p, + const char *name, + SV *sv, + modperl_handler_action_e action) +{ + I32 i; + AV *av = Nullav; + MpAV **handlers = + modperl_handler_get_handlers(r, c, s, + p, name, action); + + if (!(handlers && *handlers)) { + return FALSE; + } + + if (SvROK(sv) && (SvTYPE(SvRV(sv)) == SVt_PVAV)) { + av = (AV*)SvRV(sv); + + for (i=0; i <= AvFILL(av); i++) { + sv = *av_fetch(av, i, FALSE); + push_sv_handler; + } + } + else { + push_sv_handler; } - return avp; + return TRUE; } 1.5 +38 -1 modperl-2.0/src/modules/perl/modperl_handler.h Index: modperl_handler.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_handler.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- modperl_handler.h 2001/03/16 17:23:25 1.4 +++ modperl_handler.h 2001/03/17 06:03:37 1.5 @@ -1,6 +1,24 @@ #ifndef MODPERL_HANDLER_H #define MODPERL_HANDLER_H +typedef enum { + MP_HANDLER_ACTION_GET, + MP_HANDLER_ACTION_PUSH, + MP_HANDLER_ACTION_SET, +} modperl_handler_action_e; + +#define modperl_handler_array_new(p) \ +apr_array_make(p, 1, sizeof(modperl_handler_t *)) + +#define modperl_handler_array_push(handlers, h) \ +*(modperl_handler_t **)apr_array_push(handlers) = h + +#define modperl_handler_array_item(handlers, idx) \ +((modperl_handler_t **)(handlers)->elts)[idx] + +#define modperl_handler_array_last(handlers) \ +modperl_handler_array_item(handlers, ((handlers)->nelts - 1)) + modperl_handler_t *modperl_handler_new(apr_pool_t *p, const char *name); modperl_handler_t *modperl_handler_dup(apr_pool_t *p, @@ -12,7 +30,26 @@ modperl_config_srv_t *scfg, modperl_config_req_t *rcfg, apr_pool_t *p, - int type, int idx, int lvalue, + int type, int idx, + modperl_handler_action_e action, const char **desc); + +MpAV **modperl_handler_get_handlers(request_rec *r, conn_rec *c,server_rec *s, + apr_pool_t *p, const char *name, + modperl_handler_action_e action); + +int modperl_handler_push_handlers(pTHX_ apr_pool_t *p, + MpAV *handlers, SV *sv); + +SV *modperl_handler_perl_get_handlers(pTHX_ MpAV **handp, apr_pool_t *p); + +int modperl_handler_perl_add_handlers(pTHX_ + request_rec *r, + conn_rec *c, + server_rec *s, + apr_pool_t *p, + const char *name, + SV *sv, + modperl_handler_action_e action); #endif /* MODPERL_HANDLER_H */ 1.8 +25 -0 modperl-2.0/src/modules/perl/modperl_mgv.c Index: modperl_mgv.c =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_mgv.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- modperl_mgv.c 2001/03/16 07:30:23 1.7 +++ modperl_mgv.c 2001/03/17 06:03:37 1.8 @@ -96,6 +96,31 @@ return symbol; } +char *modperl_mgv_name_from_sv(pTHX_ apr_pool_t *p, SV *sv) +{ + char *name = NULL; + GV *gv; + + if (SvROK(sv)) { + sv = SvRV(sv); + } + + switch (SvTYPE(sv)) { + case SVt_PV: + name = SvPVX(sv); + break; + case SVt_PVCV: + if (CvANON((CV*)sv)) { + Perl_croak(aTHX_ "anonymous handlers not (yet) supported"); + } + gv = CvGV((CV*)sv); + name = apr_pstrcat(p, HvNAME(GvSTASH(gv)), "::", GvNAME(gv), NULL); + break; + }; + + return name; +} + void modperl_mgv_append(pTHX_ apr_pool_t *p, modperl_mgv_t *symbol, const char *name) { 1.3 +2 -0 modperl-2.0/src/modules/perl/modperl_mgv.h Index: modperl_mgv.h =================================================================== RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_mgv.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- modperl_mgv.h 2001/03/15 05:39:07 1.2 +++ modperl_mgv.h 2001/03/17 06:03:37 1.3 @@ -5,6 +5,8 @@ modperl_mgv_t *modperl_mgv_compile(pTHX_ apr_pool_t *p, const char *name); +char *modperl_mgv_name_from_sv(pTHX_ apr_pool_t *p, SV *sv); + GV *modperl_mgv_lookup(pTHX_ modperl_mgv_t *symbol); GV *modperl_mgv_lookup_autoload(pTHX_ modperl_mgv_t *symbol, 1.3 +38 -0 modperl-2.0/xs/Apache/RequestUtil/Apache__RequestUtil.h Index: Apache__RequestUtil.h =================================================================== RCS file: /home/cvs/modperl-2.0/xs/Apache/RequestUtil/Apache__RequestUtil.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- Apache__RequestUtil.h 2001/03/13 07:50:19 1.2 +++ Apache__RequestUtil.h 2001/03/17 06:03:37 1.3 @@ -1,3 +1,41 @@ +static MP_INLINE +int mpxs_Apache__RequestRec_push_handlers(request_rec *r, + const char *name, + SV *sv) +{ + dTHX; /*XXX*/ + return modperl_handler_perl_add_handlers(aTHX_ + r, NULL, r->server, r->pool, + name, sv, + MP_HANDLER_ACTION_PUSH); + +} + +static MP_INLINE +int mpxs_Apache__RequestRec_set_handlers(request_rec *r, + const char *name, + SV *sv) +{ + dTHX; /*XXX*/ + return modperl_handler_perl_add_handlers(aTHX_ + r, NULL, r->server, r->pool, + name, sv, + MP_HANDLER_ACTION_SET); +} + +static MP_INLINE +SV *mpxs_Apache__RequestRec_get_handlers(request_rec *r, + const char *name) +{ + dTHX; /*XXX*/ + MpAV **handp = + modperl_handler_get_handlers(r, NULL, r->server, + r->pool, name, + MP_HANDLER_ACTION_GET); + + return modperl_handler_perl_get_handlers(aTHX_ handp, r->pool); +} + /* * XXX: these three should be part of the apache api * for protocol module helpers 1.1 modperl-2.0/xs/Apache/ServerUtil/Apache__ServerUtil.h Index: Apache__ServerUtil.h =================================================================== static MP_INLINE int mpxs_Apache__Server_push_handlers(server_rec *s, const char *name, SV *sv) { dTHX; /*XXX*/ return modperl_handler_perl_add_handlers(aTHX_ NULL, NULL, s, s->process->pconf, name, sv, MP_HANDLER_ACTION_PUSH); } static MP_INLINE int mpxs_Apache__Server_set_handlers(server_rec *s, const char *name, SV *sv) { dTHX; /*XXX*/ return modperl_handler_perl_add_handlers(aTHX_ NULL, NULL, s, s->process->pconf, name, sv, MP_HANDLER_ACTION_SET); } static MP_INLINE SV *mpxs_Apache__Server_get_handlers(server_rec *s, const char *name) { dTHX; /*XXX*/ MpAV **handp = modperl_handler_get_handlers(NULL, NULL, s, s->process->pconf, name, MP_HANDLER_ACTION_GET); return modperl_handler_perl_get_handlers(aTHX_ handp, s->process->pconf); } 1.5 +6 -0 modperl-2.0/xs/maps/apache_functions.map Index: apache_functions.map =================================================================== RCS file: /home/cvs/modperl-2.0/xs/maps/apache_functions.map,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- apache_functions.map 2001/03/13 07:50:22 1.4 +++ apache_functions.map 2001/03/17 06:03:38 1.5 @@ -44,6 +44,9 @@ !ap_content_type_tolower ap_get_status_line ap_is_initial_req + mpxs_Apache__RequestRec_push_handlers + mpxs_Apache__RequestRec_set_handlers + mpxs_Apache__RequestRec_get_handlers #protocol module helpers mpxs_Apache__RequestRec_location_merge @@ -134,6 +137,9 @@ ap_construct_server ap_construct_url | | r,uri,p ap_error_log2stderr + mpxs_Apache__Server_push_handlers + mpxs_Apache__Server_set_handlers + mpxs_Apache__Server_get_handlers #MODULE=Apache::ServerConfig ap_exists_config_define