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