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
  
  
  

Reply via email to