Changes between Version 12 and Version 13 of ModParrotArchitecture

11/29/08 17:09:16 (13 years ago)



  • ModParrotArchitecture

    v12 v13  
    8585=== Metahandlers === 
     87=== Tracking === 
     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. 
     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: 
     93 * hook registration 
     94 * metahandler callbacks 
     95 * cleanup handlers 
     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: 
     100    /* initialize the index to 0 for the first module only */ 
     101    static int module_index = 0; 
     104and retrieve the module structure: 
     106    mpcfg = ap_get_module_config(our_server->module_config, &parrot_module); 
     107    modp = ((module **)mpcfg->module_array->elts)[module_index]; 
     110and finally increment the index for the next call: 
     112    /* prepare for the next module */ 
     113    module_index++; 
     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. 
     118The per-hook module array is maintained in the mod_parrot server config: 
     121apr_array_header_t *handler_modules[MP_HOOK_LAST]; 
     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: 
     127    /* get next module in line */ 
     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: 
     134static int modparrot_pre_connection_handler(conn_rec *c, void *csd) 
     136    modparrot_context *ctxp; 
     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    } 
     144    /* we're REALLY_FIRST, so reset the module index */ 
     145    ctxp->module_index = -1; 
     147    /* clean up */ 
     148    release_ctx(ctxp); 
     150    /* we only do setup */ 
     151    return DECLINED; 
    87155== Multiprocessing Module Support ==