Changes between Version 12 and Version 13 of ModParrotArchitecture

Show
Ignore:
Timestamp:
11/29/08 17:09:16 (6 years ago)
Author:
jhorwitz
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • ModParrotArchitecture

    v12 v13  
    8585=== Metahandlers === 
    8686 
     87=== Tracking === 
     88 
     89Apache makes an obvious but significant assumption about module code.  It assumes your code knows the module to which it belongs.  So the code for mod_cgi KNOWS it's part of mod_cgi, and, as an example, its response handler can ask for the mod_cgi configuration structure appropriately.  So Apache provides no infrastructure for asking it what module code it's currently executing -- it assumes you know who you are. 
     90 
     91This is a big problem for mod_parrot, which provides SHARED hooks to support multiple HLL modules.  The same hook is called regardless of which HLL module is currently in scope, and Apache won't tell you which module it is.  This comes into play in three places: 
     92 
     93 * hook registration 
     94 * metahandler callbacks 
     95 * cleanup handlers 
     96 
     97The single function {{{register_meta_hooks}}} is called to register an HLL module's hooks with Apache.  Since this function is called for every HLL module, we can maintain state within the function by using a static variable.  In particular, that variable can be an index into the global module array in the mod_parrot server config.  And since it's only run once at startup, we can initialize it to zero at the first invocation: 
     98 
     99{{{ 
     100    /* initialize the index to 0 for the first module only */ 
     101    static int module_index = 0; 
     102}}} 
     103 
     104and retrieve the module structure: 
     105{{{ 
     106    mpcfg = ap_get_module_config(our_server->module_config, &parrot_module); 
     107    modp = ((module **)mpcfg->module_array->elts)[module_index]; 
     108}}} 
     109 
     110and finally increment the index for the next call: 
     111{{{ 
     112    /* prepare for the next module */ 
     113    module_index++; 
     114}}} 
     115 
     116Metahandler callbacks use a similar indexing scheme, but the situation is more complex.  Not every HLL module registers every hook, so each hook must have its own module array.  This also means that a separate index must be used for each phase.  And finally, unlike registering the hooks, the actual hooks can be called more than once, so we must somehow reset the index for each phase. 
     117 
     118The per-hook module array is maintained in the mod_parrot server config: 
     119 
     120{{{ 
     121apr_array_header_t *handler_modules[MP_HOOK_LAST]; 
     122}}} 
     123 
     124The index is maintained in the context ({{{module_index}}}).  We do this because a context is bound to the current connection and can maintain the index while not interfering with indexes from other connections.  The code to actually retrieve the next indexed module is complex, so it's been refactored to a single macro, {{{NEXT_HANDLER_MODULE}}}, which mod_parrot calls for each metahandler.  It takes a single argument, the hook: 
     125 
     126{{{ 
     127    /* get next module in line */ 
     128    modp = NEXT_HANDLER_MODULE(MP_HOOK_PRE_CONNECTION); 
     129}}} 
     130 
     131The only remaining problem is how to reset the index for each connection.  mod_parrot registers a hook for every Apache phase with the APR_HOOK_REALLY_FIRST flag so the mod_parrot hook always runs first.  It does this to reset the index before any other modules can run.  Here's the actualy mod_parrot pre_connection handler, which does nothing but reset the index: 
     132 
     133{{{ 
     134static int modparrot_pre_connection_handler(conn_rec *c, void *csd) 
     135{ 
     136    modparrot_context *ctxp; 
     137 
     138    /* initialize context */ 
     139    if (!(ctxp = init_ctx(c->base_server, c))) { 
     140        MPLOG_ERROR(c->base_server, "context initialization failed"); 
     141        return HTTP_INTERNAL_SERVER_ERROR; 
     142    } 
     143 
     144    /* we're REALLY_FIRST, so reset the module index */ 
     145    ctxp->module_index = -1; 
     146 
     147    /* clean up */ 
     148    release_ctx(ctxp); 
     149 
     150    /* we only do setup */ 
     151    return DECLINED; 
     152} 
     153}}} 
     154 
    87155== Multiprocessing Module Support == 
    88156