28 #include "asterisk/res_pjsip.h"
29 #include "include/res_pjsip_private.h"
30 #include "asterisk/res_pjsip_cli.h"
35 #define TASK_BUCKETS 53
39 static int task_count;
74 static int push_to_serializer(
const void *data);
80 static int run_task(
void *data)
86 if (!schtd->interval) {
92 ast_log(LOG_DEBUG,
"Sched %p: Running %s\n", schtd, schtd->name);
96 schtd->is_running = 1;
100 res = schtd->task(schtd->task_data);
103 schtd->is_running = 0;
118 schtd->interval = res;
122 delay = schtd->interval;
128 schtd->next_periodic =
ast_tvadd(schtd->next_periodic,
135 schtd->current_scheduler_id =
ast_sched_add(scheduler_context, delay, push_to_serializer, schtd);
136 if (schtd->current_scheduler_id < 0) {
139 ast_log(LOG_ERROR,
"Sched %p: Failed to reschedule task %s\n", schtd, schtd->name);
146 ast_log(LOG_DEBUG,
"Sched %p: Rescheduled %s for %d ms\n", schtd, schtd->name,
157 static int push_to_serializer(
const void *data)
172 ast_log(LOG_DEBUG,
"Sched %p: Ready to run %s\n", schtd, schtd->
name);
174 ao2_t_ref(schtd, +1,
"Give ref to run_task()");
185 ao2_t_ref(schtd, -1,
"Failed so release run_task() ref");
197 ast_log(LOG_DEBUG,
"Sched %p: Canceling %s\n", schtd, schtd->
name);
223 if (ast_strlen_zero(name)) {
239 int *interval,
int *time_left,
struct timeval *next_start)
243 memcpy(queued, &schtd->
when_queued,
sizeof(
struct timeval));
246 memcpy(last_start, &schtd->
last_start,
sizeof(
struct timeval));
249 memcpy(last_end, &schtd->
last_end,
sizeof(
struct timeval));
256 if (time_left || next_start) {
258 struct timeval since_when;
274 delay = delay < 0 ? 0 : delay;
283 memcpy(next_start, &next,
sizeof(
struct timeval));
300 struct timeval *queued,
struct timeval *last_start,
struct timeval *last_end)
306 struct timeval *queued,
struct timeval *last_start,
struct timeval *last_end,
307 int *interval,
int *time_left,
struct timeval *next_start)
312 if (ast_strlen_zero(name)) {
361 if (ast_strlen_zero(name)) {
385 if (ast_strlen_zero(name)) {
399 static void schtd_dtor(
void *data)
404 ast_log(LOG_DEBUG,
"Sched %p: Destructor %s\n", schtd, schtd->
name);
416 int interval, ast_sip_task sip_task,
const char *
name,
void *
task_data,
427 schtd = ao2_alloc((
sizeof(*schtd) + (!ast_strlen_zero(name) ? strlen(name) : ID_LEN) + 1),
435 schtd->
task = sip_task;
439 if (!ast_strlen_zero(name)) {
440 strcpy(schtd->
name, name);
445 sprintf(schtd->
name,
"task_%08x", task_id);
448 ast_log(LOG_DEBUG,
"Sched %p: Scheduling %s for %d ms\n", schtd, schtd->
name,
475 res =
ast_sched_add(scheduler_context, interval, push_to_serializer, schtd);
488 #define TIME_FORMAT "%a %T"
506 e->
command =
"pjsip show scheduled_tasks";
507 e->
usage =
"Usage: pjsip show scheduled_tasks [ like <pattern> ]\n"
508 " Show scheduled pjsip tasks\n";
514 if (a->argc != 3 && a->argc != 5) {
515 return CLI_SHOWUSAGE;
520 if (strcasecmp(a->argv[3],
"like")) {
521 return CLI_SHOWUSAGE;
523 regrc = regcomp(®ex, a->argv[4], REG_EXTENDED | REG_ICASE | REG_NOSUB);
526 regerror(regrc, ®ex, err, 256);
527 ast_cli(a->fd,
"PJSIP Scheduled Tasks: Error: %s\n", err);
535 ast_sip_sched_task_sort_fn, NULL);
537 ast_cli(a->fd,
"PJSIP Scheduled Tasks: Unable to allocate temporary container\n");
542 ast_cli(a->fd,
"PJSIP Scheduled Tasks: Unable to sort temporary container\n");
550 ast_cli(a->fd,
"PJSIP Scheduled Tasks:\n\n");
553 "<Task Name....................................> <Interval> <Times Run> <State>"
554 " <Queued....> <Last Start> <Next Start.....secs>\n"
555 "=============================================================================="
556 "===================================================\n");
559 for (; (schtd = ao2_iterator_next(&iter));
ao2_ref(schtd, -1)) {
565 if (using_regex && regexec(®ex, schtd->
name, 0, NULL, 0) == REG_NOMATCH) {
571 if (next_run_sec < 0) {
582 ast_strftime(last_start,
sizeof(last_start), TIME_FORMAT, &tm);
585 ast_strftime(next_start,
sizeof(next_start), TIME_FORMAT, &tm);
587 sprintf(times_run,
"%d", schtd->
run_count);
589 ast_cli(a->fd,
"%-46.46s %9d %9s %-5s %-12s %-12s %-12s %8d\n",
611 AST_CLI_DEFINE(cli_show_tasks,
"Show pjsip scheduled tasks"),
617 if (!scheduler_context) {
618 ast_log(LOG_ERROR,
"Failed to create scheduler. Aborting load\n");
623 ast_log(LOG_ERROR,
"Failed to start scheduler. Aborting load\n");
630 ast_sip_sched_task_sort_fn, ast_sip_sched_task_cmp_fn);
632 ast_log(LOG_ERROR,
"Failed to allocate task container. Aborting load\n");
642 int ast_sip_destroy_scheduler(
void)
646 if (scheduler_context) {
653 while ((schtd = ao2_iterator_next(&iter))) {
661 scheduler_context = NULL;
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
ast_sip_scheduler_task_flags
Task flags for the res_pjsip scheduler.
Asterisk main include file. File version handling, generic pbx functions.
AO2_STRING_FIELD_HASH_FN(transport_monitor, key)
Hashing function for struct transport_monitor.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
The arg parameter is a search key, but is not an object.
struct timeval last_start
int ast_sip_sched_task_cancel(struct ast_sip_sched_task *schtd)
Cancels the next invocation of a task.
descriptor for a cli entry.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
struct timeval when_queued
AO2_STRING_FIELD_CMP_FN(transport_monitor, key)
Comparison function for struct transport_monitor.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
int ast_sip_sched_task_get_times_by_name(const char *name, struct timeval *queued, struct timeval *last_start, struct timeval *last_end)
Gets the last start and end times of the task by name.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int ast_sip_sched_is_task_running(struct ast_sip_sched_task *schtd)
Checks if the task is currently running.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
struct ast_sip_sched_task * ast_sip_schedule_task(struct ast_taskprocessor *serializer, int interval, ast_sip_task sip_task, const char *name, void *task_data, enum ast_sip_scheduler_task_flags flags)
Schedule a task to run in the res_pjsip thread pool.
int ast_sip_sched_task_get_next_run_by_name(const char *name)
Gets the number of milliseconds until the next invocation.
struct timeval next_periodic
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
int ast_sip_sched_task_get_times(struct ast_sip_sched_task *schtd, struct timeval *queued, struct timeval *last_start, struct timeval *last_end)
Gets the last start and end times of the task.
int ast_sip_sched_task_get_times_by_name2(const char *name, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run by task name.
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
int ast_sip_sched_is_task_running_by_name(const char *name)
Checks if the task is currently running.
#define ao2_unlink(container, obj)
Remove an object from a container.
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
int ast_sip_push_task(struct ast_taskprocessor *serializer, int(*sip_task)(void *), void *task_data)
Pushes a task to SIP servants.
int ast_sip_sched_task_get_times2(struct ast_sip_sched_task *schtd, struct timeval *queued, struct timeval *last_start, struct timeval *last_end, int *interval, int *time_left, struct timeval *next_start)
Gets the queued, last start, last_end, time left, interval, next run.
enum ast_sip_scheduler_task_flags flags
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
userdata associated with baseline taskprocessor test
int ast_sip_initialize_scheduler(void)
Initialize scheduler.
The next invocation of the task is at last finish + interval.
int ast_sip_sched_task_get_next_run(struct ast_sip_sched_task *schtd)
Gets the number of milliseconds until the next invocation.
int ast_sched_del(struct ast_sched_context *con, int id) attribute_warn_unused_result
Deletes a scheduled event.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
An API for managing task processing threads that can be shared across modules.
int ast_sched_add(struct ast_sched_context *con, int when, ast_sched_cb callback, const void *data) attribute_warn_unused_result
Adds a scheduled event.
The scheduled task's events are tracked in the debug log.
A ast_taskprocessor structure is a singleton by name.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
struct ast_taskprocessor * serializer
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Reject objects with duplicate keys in container.
AO2_STRING_FIELD_SORT_FN(transport_monitor, key)
Sort function for struct transport_monitor.
int ast_sip_sched_task_get_name(struct ast_sip_sched_task *schtd, char *name, size_t maxlen)
Gets the task name.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
int ast_sip_sched_task_cancel_by_name(const char *name)
Cancels the next invocation of a task by name.
#define ao2_link(container, obj)
Add an object to a container.