User provided hooks

pfalcon edited this page Jan 12, 2013 · 2 revisions

KLone (Ver 2.x and 3.x) supports user-provided hooks.

Developers can let KLone call their own functions on interesting events (see below). To enable this functionality KLone must be configured with --enable_hooks. When compiled this way KLone will call hooks_setup() to give the user the opportunity to register his hooks.

You can define hooks_setup() in a .kl1 page or in any other C file that gets linked to the main KLone daemon.

Currently supported events are:

  • Server Startup: called when the server starts;
  • Server Shutdown: called just before the server dies;
  • Children Init: called when a new worker child process is spawn;
  • Children Term: called just before a worker child dies;
  • On Request: called on every HTTP request served.

If you want to receive notifications for any of those events you have to register your own callback function with KLone. Every event has its own registration function.

Here is the current list of functions (see klone/hook.h for the updated list):

int hook_server_init( hook_server_init_t func );
int hook_server_term( hook_server_term_t func );
int hook_child_init( hook_child_init_t func );
int hook_child_term( hook_child_term_t func );
int hook_request( hook_request_t func );

For example if you want to be notified for any child process spawn by KLone to handle incoming HTTP connection (for example to create a database connection for each worker process) you can hook the child_init/child_term events:

int child_init(void)
{
    /* a new child has been forked, tear-up the always on DB connection */
    db_connect(...);
    return 0;
}

int child_term(void)
{
    /* this child is about to die, cleanly shutdown the DB connection */
    db_shutdown(...);

    return 0;
}

void hooks_setup(void)
{
    /* set hooks */
    hook_child_init( child_init );
    hook_child_term( child_term );

}

Another example.

If you want to store in a database all IP address of all clients you can hook the child_init/child_term events like above to connect to the database and the request event to add the IP of the client to the DB for every request:

int on_request(request_t *rq, response_t *rs)
{
    const char *ip;
    addr_t *addr;

    /* log only successfull requests */
    if(response_get_status(rs) == HTTP_STATUS_OK)
    {
        addr = request_get_addr(rq);
        ip = inet_ntoa(addr->sa.sin.sin_addr);

        db_insert(..., ip, ...);
    }

    return 0;
}

int child_init(void)
{
    /* a new child has been forked, tear-up the always on DB connection */
    db_connect(...);
    return 0;
}

int child_term(void)
{                                
    /* this child is about to die, cleanly shutdown the DB connection */
    db_shutdown(...);

    return 0;             
}                 

void hooks_setup(void)
{                 
    /* set hooks */
    hook_child_init( child_init );
    hook_child_term( child_term );
    hook_request( request );
}

Same applies for server_init/server_term hooks that you can use to setup your per-server singleton objects, create resources shared by children processes, etc.