/*
 *  SYNOPSIS
 *
 *    Main Setup:
 *      void ap_hook_init (void);
 *      void ap_hook_kill (void);
 *
 *    Hook Configuration and Registration:
 *      ap_hook_define_client(hook_name,hook_parameters,hook_call);
 *      int  ap_hook_configure_hook_name(ap_hook_mode modeid);
 *      int  ap_hook_unconfigure_hook_name();
 *
 *      ap_hook_define_server(hook_name,hook_parameters,hook_call);
 *      int  ap_hook_register_hook_name(int (*func)hook_parameters);
 *      int  ap_hook_unregister_hook_name(int (*func)hook_parameters);
 *
 *      ap_hook_define_client_global(mod_name,hook_name,hook_parameters,hook_call);
 *      ap_hook_define_client_realize(mod_name,hook_name,hook_parameters,hook_call);
 *      int  ap_hook_mod_name_configure_hook_name(ap_hook_mode modeid);
 *      int  ap_hook_mod_name_unconfigure_hook_name();
 *
 *      ap_hook_define_server_global(mod_name,hook_name,hook_parameters,hook_call);
 *      ap_hook_define_server_realize(mod_name,hook_name,hook_parameters,hook_call);
 *      int  ap_hook_mod_name_register_hook_name(int (*func)hook_parameters);
 *      int  ap_hook_mod_name_unregister_hook_name(int (*func)hook_parameters);
 *
 *    Hook Usage:
 *      int  ap_hook_configured_hook_name();
 *      int  ap_hook_registered_hook_name();
 *      int  ap_hook_registered_func_hook_name(int (*func)hook_parameters);
 *      int  ap_hook_hook_name(hook_parameters);
 *
 *      int  ap_hook_mod_name_configured_hook_name();
 *      int  ap_hook_mod_name_registered_hook_name();
 *      int  ap_hook_mod_name_registered_func_hook_name(int (*func)hook_parameters);
 *      int  ap_hook_mod_name_hook_name(hook_parameters);
 *
 *  DESCRIPTION
 *
 *    This implements a generic hook interface for Apache which can be used
 *    for loosely couple code through arbitrary hooks. There are two use cases
 *    for this mechanism:
 *
 *    1. Inside a specific code section you want to perform a specific
 *       function call. But you want to allow one or even more modules to
 *       override this function call by registering hook functions.  Those
 *       functions are registered on a stack and could return TRUE or FALSE.
 *       As long as there are functions which return FALSE value the next
 *       function on the stack is tried.  When a function return TRUE the
 *       hook call stops.  The intent of this usage is to not hard-code
 *       function calls.  Note that the only return type allowed for hooks
 *       is int and only two values could be returned: TRUE and FALSE. If
 *       you want other return types or values use wrappers (see sample below).
 *
 *    2. Inside a specific code you have a function you want to export.
 *       But you first want to allow other code to override this function.
 *       And second you want to export this function without real linker
 *       symbol references. Instead you want to register the function and let
 *       the users call this function via name. The intent of this usage is to
 *       allow inter-module communication without direct symbol references,
 *       which are a big NO-NO for the DSO situation.
 *
 *    And we have one major design goal: The hook call should be very similar
 *    to the corresponding direct function call while still providing maximum
 *    flexiblity, i.e. any function signature (the set of types for arguments)
 *    should be supported.  If you need return value use wrappers.
 *
 *    Using this hook interface is always a four-step process(but see also
 *    "NOTE for DSO modules" below!):
 *
 *    1. Initialize or destroy the hook mechanism inside your main program:
 *
 *       ap_hook_init();
 *           :
 *       ap_hook_kill();
 *
 *    2. Define and configure a particular hook by specifing its name and
 *       argumets type:
 *
 *       ap_hook_define_client(lookup,(void **r,void *x),(r,x));
 *       ap_hook_define_client(echo,(int *r,void *x),(r,x));
 *
 *       ap_hook_configure_lookup(AP_HOOK_NORMAL);
 *       ap_hook_configure_echo(AP_HOOK_TOPMOST);
 *
 *       This configures two hooks:
 *       - A hook named "lookup" with the signature "lookup(void **,void *)"
 *         and default return semantic.
 *       - A hook named "echo" with the signature "echo(int *,void *)" and a
 *         return code semantic which says: Only the top most function on the
 *         registered function stack is tried, independed what value it
 *         returns.
 *
 *    3. Define and register the actual functions which should be used by
 *       the hook:
 *
 *       ap_hook_define_server(lookup,(void **r,void *x),(r,x));
 *       ap_hook_define_server(echo,(int *r,void *x),(r,x));
 *
 *       static int mylookup_wrapper(void **r,void *x) {
 *         *r=mylookup(x);
 *         if (*r) return TRUE; else return FALSE;
 *       }
 *       static int myecho_wrapper(int *r,void *x) {
 *         *r=myecho(*r,x);
 *         return TRUE;
 *       }
 *
 *       ap_hook_register_lookup(mylookup);
 *       ap_hook_register_echo(myecho);
 *
 *       This registers the function mylookup() under the "lookup" hook and
 *       function myecho() under the "echo" hook.
 *
 *    4. Finally use the hook, i.e. instead of using direct function calls
 *       like
 *
 *          vp = mylookup("foo");
 *          n  = myecho("bar");
 *
 *       you now can use:
 *
 *          ap_hook_call_lookup(&vp, "foo");
 *          ap_hook_call_echo(&n, "bar");
 *
 *       BTW, the return value of ap_hook_call() is TRUE or FALSE.  TRUE when
 *       at least one function call was successful (not always the case even
 *       for AP_HOOK_TOPMOST: if the only checked function will return FALSE
 *       this will be returned; the same if hook still is not registered).
 *       FALSE when all functions returned FALSE or no functions are registered
 *       at all.
 *
 *  NOTE for DSO modules
 *
 *       If you plan to use this mechanism in DSO modules you SHOULD unregister
 *       all hooks on module unload phase:
 *
 *       static void unregister_hooks(struct module_struct * m) {
 *           if (m == &client_module) {
 *               ap_hook_configure_lookup();
 *               ap_hook_configure_echo();
 *           }
 *       }
 *
 *       static void unregister_hooks(struct module_struct * m) {
 *           if (m == &server_module) {
 *               ap_hook_unregister_lookup(mylookup);
 *               ap_hook_unregister_echo(myecho);
 *           }
 *       }
 *
 *       Insert unregister_hooks function as remove_module hook in module
 *       structure.
 *
 *  NOTE for modules with multiple source files
 *
 *       It's safe to use ap_hook_define_client and/or ap_hook_define_server
 *       in .h file included in multiple .c files. But if you have non-gcc
 *       based compiler this will lead to a lot of duplicated static functions.
 *       So in this case you should use ap_hook_define_client_global and/or
 *       ap_hook_define_server_global in .h file. In ONE .c file for each
 *       module you should use ap_hook_define_client_realize and/or
 *       ap_hook_define_server_realize to make instances for functions.
 *       You should include .h file with ap_hook_define_client_global and/or
 *       ap_hook_define_server_global before ap_hook_define_client_realize
 *       and/or ap_hook_define_server_realize. Unfortunatelly this usage of
 *       non-static functions could lead to namespace pollution. To avoid this
 *       all autogenerated functions will be created with prefix
 *       ap_hook_module_name instead of just ap_hook (module name is first
 *       parameter in ap_hook_define_{client,server}_{global,realize} macro).
 *
 *  SPEED ISSUES
 *
 *       This implementation is designed to be VERY fast. For example this
 *       program (direct function call):
 *
 *       void main(void) {
 *           FILE *f=fopen("/dev/null","a");
 *           for (int i=0;i<10000000;i++) fputc(' ',f);
 *           fclose(f);
 *       }
 *
 *       works 2.95 seconds on Pentium200MMX (egcs 1.1b with -O6 -mcpu=pentium).
 *
 *       This program (call over hooks):
 *
 *       ap_hook_define(fputc,(int *res,int c,FILE *stream),(res,c,stream));
 *       int fputc_wrapper(int *res,int c,FILE *stream) {
 *           *res=fputc(c,stream);
 *           return TRUE;
 *       }
 *
 *       void main(void) {
 *           FILE *f=fopen("/dev/null","a");
 *           ap_hook_register_fputc(fputc_wrapper);
 *           ap_hook_configure_fputc(AP_HOOK_NORMAL);
 *           for (int i=0;i<10000000;i++) {
 *               int dummy;
 *               ap_hook_call_fputc(&dummy,' ',f);
 *           }
 *           fclose(f);
 *       }
 *
 *       will work 3.76 seconds on the same Pentium200MMX.
 */

EAPI-2-EAPIk-4-2.1b9-SNAP.patch4.gz

Reply via email to