Login | Register

Documentation

Documentation -> Development Manual -> Timer API

This page has been visited 231 times.



Timer API

OpenSIPS exposes its own API for implementing timer functions, with seconds and microsecond precision.
The OpenSIPS timer architecture is made out of the so called 'timer keeper' , which is a process which just increments global counter of second and microsecond precision, and one process which will execute the various timer functions when their time to execute has arrived.
Also, the OpenSIPS timers support automatic re-calibration in order to compensate timer drifting in case the timer executed functions do not complete in timely manners.

1.  Global Timer Process

timer.h exposes all the relevant functionalities for operating the OpenSIPS timers. For registering a new timer function with second precision, use :

/*
Parameters :
        label – opaque string containing a short timer function description ( to be used for logging )
        f – the actual function to be called
        param – parameter to be provided to the timer function
        interval – the interval, in seconds, that the function needs to be called at
Returns :
        0 in case of success, negative code in case of internal error.
*/

int register_timer(char *label, timer_function f, void* param,
      unsigned int interval);
/*
The seconds callback
Parameters :
      ticks - represents the current number of seconds since OpenSIPS startup when the callback is called at
      param - is the parameter provided at timer function registration.
*/

typedef void (timer_function)(unsigned int ticks, void* param);


For registering a microsecond timer, you should use

/*
Parameters :
        label – opaque string containing a short timer function description ( to be used for logging )
        f – the actual function to be called
        param – parameter to be provided to the timer function
        interval – the interval, in microseconds, that the function needs to be called at
Returns :
        0 in case of success, negative code in case of internal error.
*/

int register_utimer(char *label, utimer_function f, void* param, unsigned int interval);

2.  Dedicated Timer Process

Since, by default, all the registered timer functions are called from within the same process context, in case you are writing a timer process that is doing I/O, it is better to register an entirely new process where to run your code, since your function might slow down all the other timer functions running in OpenSIPS.
Registering a new timer process can be done by calling :

/*
Parameters :
      label - opaque string containing a short timer function description ( to be used for logging )
      f - the actual function to be called
      param - parameter to be provided to the timer function
      interval - the interval, in seconds, that the function needs to be called at
      flags - flags controlling process behavior. Currently only option is TIMER_PROC_INIT_FLAG , which leads to child_init to be called in the new timer process context. To be used when inside the timer you need to operate various I/O options which generally require a per process connection.
Returns :
      struct sr_timer_process pointer in case of success, or NULL in case of error.
*/

void* register_timer_process(char *label, timer_function f, void* param,
      unsigned int interval, unsigned int flags);


The output struct sr_timer_process pointer can be further use to group together multiple functions inside the same process, by calling :

/*
Parameters:
      label – opaque string containing a short timer function description ( to be used for logging )
      f – the actual function to be called
      param – parameter to be provided to the timer function
      interval – the interval, in seconds, that the function needs to be called at
      timer – the  struct sr_timer_process pointer obtained by previously calling  register_timer_process
Returns:
      0 in case of success, negative code in case of internal error.
*/

int append_timer_to_process( char *label, timer_function f, void* param,
      unsigned int interval, void *timer);


Important to note here that all the above timer related functions MUST be called in the context of the attendant process before forking is done ( so either from the modules mod_init or directly from the core, before forking ).

Below is a code snippet exemplifying how the dialog module's code used for registering two timers, with an option to either use the global timer process or to have it's own separate timer :

if (dlg_have_own_timer_proc) {
      LM_INFO("Running with dedicated dialog timer process\n");
      dlg_own_timer_proc = register_timer_process( "dlg-timer",
            dlg_timer_routine, NULL,1,TIMER_PROC_INIT_FLAG );
      if (dlg_own_timer_proc == NULL) {
            LM_ERR("Failed to init dialog own timer proc\n");
            return -1;
      }
      if (append_timer_to_process("dlg-pinger", dlg_ping_routine, NULL,
            ping_interval,dlg_own_timer_proc) < 0) {
            LM_ERR("Failed to append ping timer \n");
            return -1;
      }
} else {
      if ( register_timer( "dlg-timer", dlg_timer_routine, NULL, 1)<0 ) {
            LM_ERR("failed to register timer \n");
            return -1;
      }

      if ( register_timer( "dlg-pinger", dlg_ping_routine, NULL,
            ping_interval)<0) {
            LM_ERR("failed to register timer 2 \n");
            return -1;
      }
}


Also, the OpenSIPS API also exposes the number of seconds and microseconds passed from the OpenSIPS start time. These can be accessed by calling

/*
Returns :
      the number of seconds elapsed from OpenSIPS start
*/

unsigned int get_ticks(void);

/*
Returns:
      the number of microseconds elapsed from OpenSIPS start
*/

utime_t get_uticks(void);

Page last modified on May 31, 2024, at 09:55 AM