libamxp  1.4.0
Patterns C Implementation
amxp_scheduler.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <stdlib.h>
60 #include <stdio.h>
61 
62 #include <amxc/amxc.h>
63 #include <amxp/amxp_scheduler.h>
64 #include <amxc/amxc_macros.h>
65 
66 static void amxp_schedule_item_delete(amxc_llist_it_t* it) {
67  amxp_scheduler_item_t* item = amxc_container_of(it, amxp_scheduler_item_t, lit);
68 
69  amxp_cron_clean(&item->cron);
70  amxp_timer_delete(&item->timer);
71  amxc_htable_it_clean(&item->hit, NULL);
72  free(item);
73 }
74 
75 static int amxp_scheduler_compare_items(amxc_llist_it_t* it1, amxc_llist_it_t* it2) {
76  amxp_scheduler_item_t* item1 = amxc_container_of(it1, amxp_scheduler_item_t, lit);
77  amxp_scheduler_item_t* item2 = amxc_container_of(it2, amxp_scheduler_item_t, lit);
78 
79  return item1->next.sec - item2->next.sec;
80 }
81 
83  amxc_llist_it_t* it = NULL;
84  amxp_scheduler_item_t* item = NULL;
85  uint64_t next = 0;
86 
87  amxc_llist_sort(&scheduler->ordered_items, amxp_scheduler_compare_items);
88  it = amxc_llist_get_first(&scheduler->ordered_items);
89  if(it == NULL) {
90  amxp_timer_stop(scheduler->timer);
91  goto exit;
92  }
93 
94  item = amxc_container_of(it, amxp_scheduler_item_t, lit);
95  next = amxp_cron_time_until_next(&item->cron, scheduler->use_local_time);
96 
97  if(scheduler->sigmngr.enabled) {
98  amxp_timer_start(scheduler->timer, next * 1000);
99  }
100 
101 exit:
102  return;
103 }
104 
105 static void amxp_scheduler_emit(amxp_scheduler_t* scheduler,
106  amxp_scheduler_item_t* item,
107  const char* signal,
108  uint32_t duration,
109  bool trigger) {
110  amxc_var_t data;
111  amxc_string_t strsignal;
112  amxp_signal_t* s = NULL;
113  const char* id = amxc_htable_it_get_key(&item->hit);
114  amxc_var_init(&data);
115  amxc_var_set_type(&data, AMXC_VAR_ID_HTABLE);
116  amxc_var_add_key(cstring_t, &data, "id", id);
117  amxc_string_init(&strsignal, 0);
118 
119  amxc_string_setf(&strsignal, "%s:%s", signal, id);
120 
121  if(duration != 0) {
122  amxc_var_add_key(uint32_t, &data, "duration", duration);
123  }
124 
125  amxc_var_add_key(cstring_t, &data, "reason", signal);
126 
127  s = amxp_sigmngr_find_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0));
128  when_null(s, exit);
129  if(trigger) {
130  if(!s->triggered) {
131  amxp_sigmngr_trigger_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0), &data);
132  }
133  } else {
134  amxp_sigmngr_emit_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0), &data);
135  }
136 
137 exit:
138  amxc_string_clean(&strsignal);
139  amxc_var_clean(&data);
140 }
141 
142 
143 static void amxp_scheduler_item_stop(UNUSED amxp_timer_t* timer, void* priv) {
145  amxp_scheduler_t* scheduler = amxc_container_of(item->lit.llist, amxp_scheduler_t, ordered_items);
146 
147  amxp_timer_delete(&item->timer);
148  amxp_scheduler_emit(scheduler, item, "stop", 0, false);
149 }
150 
152  amxp_scheduler_item_t* item) {
153  amxc_ts_t now;
154  amxc_ts_t prev = { 0, 0, 0};
155  uint32_t duration = 0;
156  amxc_ts_now(&now);
157 
158  when_false(scheduler->sigmngr.enabled, exit);
159  when_false(item->enabled, exit);
160  if((item->duration == 0) && !item->end_time_is_set) {
161  if((item->timer != NULL) && (item->timer->state == amxp_timer_running)) {
162  amxp_scheduler_emit(scheduler, item, "stop", 0, false);
163  amxp_timer_delete(&item->timer);
164  }
165  goto exit;
166  }
167 
168  if(scheduler->use_local_time) {
169  amxc_ts_to_local(&now);
170  }
171 
172  duration = item->duration;
173  amxp_cron_prev(&item->cron, &now, &prev);
174  if((duration == 0) && item->end_time_is_set) {
175  amxc_ts_t end = { 0, 0, 0};
176  amxp_cron_next(&item->end_cron, &prev, &end);
177  duration = end.sec - prev.sec;
178  }
179 
180  prev.sec += duration;
181  if(prev.sec > now.sec) {
182  if(item->timer == NULL) {
184  }
185  if(item->timer->state != amxp_timer_running) {
186  amxp_scheduler_emit(scheduler, item, "start", prev.sec - now.sec, false);
187  }
188  amxp_timer_start(item->timer, (prev.sec - now.sec) * 1000);
189  } else {
190  if((item->timer != NULL) && (item->timer->state == amxp_timer_running)) {
191  amxp_scheduler_emit(scheduler, item, "stop", 0, false);
192  amxp_timer_delete(&item->timer);
193  }
194  }
195 
196 exit:
197  return;
198 }
199 
200 static void amxp_scheduler_trigger(amxp_timer_t* timer, void* priv) {
201  amxp_scheduler_t* scheduler = (amxp_scheduler_t*) priv;
202  amxc_llist_it_t* it = amxc_llist_get_first(&scheduler->ordered_items);
203  amxp_scheduler_item_t* item = amxc_container_of(it, amxp_scheduler_item_t, lit);
204  amxc_ts_t now;
205  uint32_t duration = 0;
206 
207  when_false(timer == scheduler->timer, exit);
208  amxc_ts_now(&now);
209 
210  if(scheduler->use_local_time) {
211  amxc_ts_to_local(&now);
212  }
213 
214  while(it != NULL && item->next.sec <= now.sec) {
215  if(item->enabled) {
216  duration = item->duration;
217  if((duration == 0) && item->end_time_is_set) {
218  amxc_ts_t end = { 0, 0, 0};
219  amxp_cron_next(&item->end_cron, &now, &end);
220  duration = end.sec - now.sec;
221  }
222  if(duration == 0) {
223  amxp_scheduler_emit(scheduler, item, "trigger", 0, false);
224  } else {
225  amxp_scheduler_emit(scheduler, item, "start", duration, false);
227  amxp_timer_start(item->timer, duration * 1000);
228  }
229  }
230  amxp_cron_next(&item->cron, &now, &item->next);
231  it = amxc_llist_it_get_next(it);
232  if(it != NULL) {
233  item = amxc_container_of(it, amxp_scheduler_item_t, lit);
234  }
235  }
236 
237  amxp_scheduler_reset_timer(scheduler);
238 exit:
239  return;
240 }
241 
242 static void amxp_scheduler_add_signal(amxp_scheduler_t* scheduler, const char* signal, const char* id) {
243  amxc_string_t strsignal;
244  amxc_string_init(&strsignal, 0);
245 
246  amxc_string_setf(&strsignal, "%s:%s", signal, id);
247  amxp_sigmngr_add_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0));
248 
249  amxc_string_clean(&strsignal);
250 }
251 
252 static void amxp_scheduler_remove_signal(amxp_scheduler_t* scheduler, const char* signal, const char* id) {
253  amxc_string_t strsignal;
254  amxp_signal_t* s = NULL;
255  amxc_string_init(&strsignal, 0);
256 
257  amxc_string_setf(&strsignal, "%s:%s", signal, id);
258  s = amxp_sigmngr_find_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0));
259  if(s != NULL) {
260  if(s->triggered) {
261  amxp_sigmngr_remove_signal(&scheduler->sigmngr, amxc_string_get(&strsignal, 0));
262  } else {
263  amxp_signal_delete(&s);
264  }
265  }
266 
267  amxc_string_clean(&strsignal);
268 }
269 
271  const char* id,
272  uint32_t duration) {
273  amxp_scheduler_item_t* item = NULL;
274  amxc_htable_it_t* hit = NULL;
275  bool enabled = true;
276 
277  when_null(scheduler, exit);
278  when_str_empty(id, exit);
279 
280  hit = amxc_htable_get(&scheduler->items, id);
281  if(hit != NULL) {
282  item = amxc_container_of(hit, amxp_scheduler_item_t, hit);
283  enabled = item != NULL? item->enabled:true;
284  } else {
285  item = (amxp_scheduler_item_t*) calloc(1, sizeof(amxp_scheduler_item_t));
286  }
287  when_null(item, exit);
288 
289  item->duration = duration;
290  item->enabled = enabled;
291 
292 exit:
293  return item;
294 }
295 
297  const char* id,
298  amxp_scheduler_item_t* item) {
299 
300  amxc_ts_t now;
301 
302  amxc_ts_now(&now);
303  if(scheduler->use_local_time) {
304  amxc_ts_to_local(&now);
305  }
306 
307  amxp_cron_next(&item->cron, &now, &item->next);
308  amxc_llist_prepend(&scheduler->ordered_items, &item->lit);
309  amxc_htable_insert(&scheduler->items, id, &item->hit);
310 
311  amxp_scheduler_add_signal(scheduler, "trigger", id);
312  amxp_scheduler_add_signal(scheduler, "start", id);
313  amxp_scheduler_add_signal(scheduler, "stop", id);
314 
315  amxp_scheduler_check_item(scheduler, item);
316  amxp_scheduler_reset_timer(scheduler);
317 }
318 
320  int rv = -1;
321 
322  when_null(scheduler, exit);
323  *scheduler = (amxp_scheduler_t*) calloc(1, sizeof(amxp_scheduler_t));
324  when_null(*scheduler, exit);
325 
326  rv = amxp_scheduler_init(*scheduler);
327 
328 exit:
329  return rv;
330 }
331 
333  when_null(scheduler, exit);
334  when_null(*scheduler, exit);
335 
336  amxp_scheduler_clean(*scheduler);
337  free(*scheduler);
338  *scheduler = NULL;
339 
340 exit:
341  return;
342 }
343 
345  int rv = -1;
346 
347  when_null(scheduler, exit);
348 
349  amxp_sigmngr_init(&scheduler->sigmngr);
350  amxp_sigmngr_enable(&scheduler->sigmngr, true);
351 
352  scheduler->use_local_time = false;
353  scheduler->timer = NULL;
354  amxp_timer_new(&scheduler->timer, amxp_scheduler_trigger, scheduler);
355  amxc_htable_init(&scheduler->items, 5);
356  amxc_llist_init(&scheduler->ordered_items);
357 
358  rv = 0;
359 
360 exit:
361  return rv;
362 }
363 
365  when_null(scheduler, exit);
366  amxp_sigmngr_clean(&scheduler->sigmngr);
367  amxp_timer_delete(&scheduler->timer);
368  amxc_llist_for_each(it, &scheduler->ordered_items) {
369  amxp_scheduler_item_t* item = amxc_container_of(it, amxp_scheduler_item_t, lit);
370  if((item->timer != NULL) && (item->timer->state == amxp_timer_running)) {
371  amxp_scheduler_emit(scheduler, item, "stop", 0, true);
372  }
373  }
374  amxc_llist_clean(&scheduler->ordered_items, amxp_schedule_item_delete);
375  amxc_htable_clean(&scheduler->items, NULL); // items are freed when cleaning ordered list.
376 
377 exit:
378  return;
379 }
380 
381 int amxp_scheduler_enable(amxp_scheduler_t* scheduler, bool enable) {
382  int rv = -1;
383 
384  when_null(scheduler, exit);
385  when_true_status(scheduler->sigmngr.enabled == enable, exit, rv = 0);
386 
387  amxp_sigmngr_enable(&scheduler->sigmngr, enable);
388  if(enable) {
389  amxp_scheduler_update(scheduler);
390  amxp_scheduler_reset_timer(scheduler);
391  }
392  if(!enable) {
393  amxp_scheduler_update(scheduler);
394  amxp_timer_stop(scheduler->timer);
395  }
396 
397  rv = 0;
398 
399 exit:
400  return rv;
401 }
402 
403 int amxp_scheduler_use_local_time(amxp_scheduler_t* scheduler, bool use_local_time) {
404  int rv = -1;
405 
406  when_null(scheduler, exit);
407 
408  when_true_status(use_local_time == scheduler->use_local_time, exit, rv = 0);
409  scheduler->use_local_time = use_local_time;
410  amxp_scheduler_update(scheduler);
411 
412  rv = 0;
413 
414 exit:
415  return rv;
416 }
417 
419  int rv = -1;
420  amxc_ts_t now;
421  amxp_scheduler_item_t* item = NULL;
422 
423  amxc_ts_now(&now);
424  when_null(scheduler, exit);
425 
426  if(scheduler->use_local_time) {
427  amxc_ts_to_local(&now);
428  }
429 
430  amxc_llist_for_each(item_it, &scheduler->ordered_items) {
431  item = amxc_container_of(item_it, amxp_scheduler_item_t, lit);
432  amxp_cron_next(&item->cron, &now, &item->next);
433  if(scheduler->sigmngr.enabled) {
434  amxp_scheduler_check_item(scheduler, item);
435  } else {
436  amxp_timer_delete(&item->timer);
437  }
438  }
439 
440  amxp_scheduler_reset_timer(scheduler);
441 
442  rv = 0;
443 
444 exit:
445  return rv;
446 }
447 
449  const char* id,
450  amxp_slot_fn_t fn,
451  void* priv) {
452 
453  int rv = -1;
454  amxc_string_t signal;
455  amxc_htable_it_t* hit = NULL;
456  amxp_scheduler_item_t* item = NULL;
457 
458  amxc_string_init(&signal, 0);
459  when_null(scheduler, exit);
460 
461  if((id == NULL) || (*id == 0)) {
462  // connect to all signals
463  rv = amxp_slot_connect(&scheduler->sigmngr, "*", NULL, fn, priv);
464  goto exit;
465  }
466 
467  hit = amxc_htable_get(&scheduler->items, id);
468  when_null(hit, exit);
469  item = amxc_container_of(hit, amxp_scheduler_item_t, hit);
470  when_null(item, exit);
471 
472  amxc_string_setf(&signal, "start:%s", id);
473  rv = amxp_slot_connect(&scheduler->sigmngr, amxc_string_get(&signal, 0), NULL, fn, priv);
474  when_failed(rv, exit);
475  amxc_string_setf(&signal, "stop:%s", id);
476  rv = amxp_slot_connect(&scheduler->sigmngr, amxc_string_get(&signal, 0), NULL, fn, priv);
477  when_failed(rv, exit);
478  amxc_string_setf(&signal, "trigger:%s", id);
479  rv = amxp_slot_connect(&scheduler->sigmngr, amxc_string_get(&signal, 0), NULL, fn, priv);
480 
481 exit:
482  amxc_string_clean(&signal);
483  return rv;
484 }
485 
487  const char* id,
488  amxp_slot_fn_t fn) {
489 
490  int rv = -1;
491  amxc_string_t signal;
492  amxc_htable_it_t* hit = NULL;
493  amxp_scheduler_item_t* item = NULL;
494 
495  amxc_string_init(&signal, 0);
496  when_null(scheduler, exit);
497 
498  if((id == NULL) || (*id == 0)) {
499  // connect to all signals
501  rv = 0;
502  goto exit;
503  }
504 
505  hit = amxc_htable_get(&scheduler->items, id);
506  when_null(hit, exit);
507  item = amxc_container_of(hit, amxp_scheduler_item_t, hit);
508  when_null(item, exit);
509 
510  amxc_string_setf(&signal, "start:%s", id);
511  rv = amxp_slot_disconnect(&scheduler->sigmngr, amxc_string_get(&signal, 0), fn);
512  when_failed(rv, exit);
513  amxc_string_setf(&signal, "stop:%s", id);
514  rv = amxp_slot_disconnect(&scheduler->sigmngr, amxc_string_get(&signal, 0), fn);
515  when_failed(rv, exit);
516  amxc_string_setf(&signal, "trigger:%s", id);
517  rv = amxp_slot_disconnect(&scheduler->sigmngr, amxc_string_get(&signal, 0), fn);
518 
519 exit:
520  amxc_string_clean(&signal);
521  return rv;
522 }
523 
525  const char* id,
526  const char* cron_expr,
527  uint32_t duration) {
528  int rv = -1;
529  amxp_scheduler_item_t* item = NULL;
530 
531  when_str_empty(cron_expr, exit);
532 
533  item = amxp_scheduler_create_or_fetch(scheduler, id, duration);
534  when_null(item, exit);
535 
536  item->end_time_is_set = false;
537 
538  rv = amxp_cron_parse_expr(&item->cron, cron_expr, NULL);
539  when_failed(rv, exit);
540 
541  amxp_scheduler_insert(scheduler, id, item);
542 
543 exit:
544  if((rv != 0) && (item != NULL)) {
545  amxc_llist_it_clean(&item->lit, amxp_schedule_item_delete);
546  }
547  return rv;
548 }
549 
551  const char* id,
552  const char* cron_begin,
553  const char* cron_end) {
554  int rv = -1;
555  amxp_scheduler_item_t* item = NULL;
556 
557  when_str_empty(cron_begin, exit);
558  when_str_empty(cron_end, exit);
559 
560  item = amxp_scheduler_create_or_fetch(scheduler, id, 0);
561  when_null(item, exit);
562 
563  item->end_time_is_set = true;
564 
565  rv = amxp_cron_parse_expr(&item->cron, cron_begin, NULL);
566  when_failed(rv, exit);
567  rv = amxp_cron_parse_expr(&item->end_cron, cron_end, NULL);
568  when_failed(rv, exit);
569 
570  amxp_scheduler_insert(scheduler, id, item);
571 
572 exit:
573  if((rv != 0) && (item != NULL)) {
574  amxc_llist_it_clean(&item->lit, amxp_schedule_item_delete);
575  }
576  return rv;
577 }
578 
580  const char* id,
581  const char* time,
582  const char* days_of_week,
583  uint32_t duration) {
584  int rv = -1;
585  amxp_scheduler_item_t* item = NULL;
586 
587  when_str_empty(days_of_week, exit);
588 
589  if((time == NULL) || (*time == 0)) {
590  time = "00:00";
591  }
592 
593  item = amxp_scheduler_create_or_fetch(scheduler, id, duration);
594  when_null(item, exit);
595 
596  item->end_time_is_set = false;
597 
598  rv = amxp_cron_build_weekly(&item->cron, time, days_of_week);
599  when_failed(rv, exit);
600 
601  amxp_scheduler_insert(scheduler, id, item);
602 
603 exit:
604  if((rv != 0) && (item != NULL)) {
605  amxc_llist_it_clean(&item->lit, amxp_schedule_item_delete);
606  }
607  return rv;
608 }
609 
611  const char* id,
612  const char* start_time,
613  const char* end_time,
614  const char* days_of_week) {
615  int rv = -1;
616  amxp_scheduler_item_t* item = NULL;
617 
618  when_str_empty(days_of_week, exit);
619 
620  if((start_time == NULL) || (*start_time == 0)) {
621  start_time = "00:00";
622  }
623 
624  if((end_time == NULL) || (*end_time == 0)) {
625  end_time = "23:59";
626  }
627 
628  item = amxp_scheduler_create_or_fetch(scheduler, id, 0);
629  when_null(item, exit);
630 
631  item->end_time_is_set = true;
632 
633  rv = amxp_cron_build_weekly(&item->cron, start_time, days_of_week);
634  when_failed(rv, exit);
635  rv = amxp_cron_build_weekly(&item->end_cron, end_time, days_of_week);
636  when_failed(rv, exit);
637 
638  amxp_scheduler_insert(scheduler, id, item);
639 
640 exit:
641  if((rv != 0) && (item != NULL)) {
642  amxc_llist_it_clean(&item->lit, amxp_schedule_item_delete);
643  }
644  return rv;
645 }
646 
648  const char* id) {
649 
650  int rv = -1;
651  amxc_htable_it_t* hit = NULL;
652  amxp_scheduler_item_t* item = NULL;
653 
654  when_null(scheduler, exit);
655  when_str_empty(id, exit);
656 
657  hit = amxc_htable_get(&scheduler->items, id);
658  when_null_status(hit, exit, rv = 0);
659  item = amxc_container_of(hit, amxp_scheduler_item_t, hit);
660 
661  amxc_htable_it_take(hit);
662  if((item->timer != NULL) && (item->timer->state == amxp_timer_running)) {
663  amxp_timer_stop(item->timer);
664  amxp_scheduler_emit(scheduler, item, "stop", 0, true);
665  }
666 
667  amxp_scheduler_remove_signal(scheduler, "start", id);
668  amxp_scheduler_remove_signal(scheduler, "stop", id);
669  amxp_scheduler_remove_signal(scheduler, "trigger", id);
670 
671  amxc_llist_it_clean(&item->lit, amxp_schedule_item_delete);
672  amxp_scheduler_reset_timer(scheduler);
673 
674  rv = 0;
675 
676 exit:
677  return rv;
678 }
679 
681  const char* id,
682  bool enable) {
683  int rv = -1;
684  amxc_htable_it_t* hit = NULL;
685  amxp_scheduler_item_t* item = NULL;
686 
687  when_null(scheduler, exit);
688  when_str_empty(id, exit);
689 
690  hit = amxc_htable_get(&scheduler->items, id);
691  when_null(hit, exit);
692  item = amxc_container_of(hit, amxp_scheduler_item_t, hit);
693  when_true_status(enable == item->enabled, exit, rv = 0);
694 
695  item->enabled = enable;
696  if(!enable) {
697  if((item->timer != NULL) && (item->timer->state == amxp_timer_running)) {
698  amxp_scheduler_emit(scheduler, item, "stop", 0, false);
699  amxp_timer_delete(&item->timer);
700  }
701  } else {
702  amxp_scheduler_check_item(scheduler, item);
703  amxp_scheduler_reset_timer(scheduler);
704  }
705 
706  rv = 0;
707 
708 exit:
709  return rv;
710 }
711 
713  amxp_signal_mngr_t* sigmngr = NULL;
714  when_null(scheduler, exit);
715 
716  sigmngr = &scheduler->sigmngr;
717 
718 exit:
719  return sigmngr;
720 }
static void amxp_scheduler_insert(amxp_scheduler_t *scheduler, const char *id, amxp_scheduler_item_t *item)
static amxp_scheduler_item_t * amxp_scheduler_create_or_fetch(amxp_scheduler_t *scheduler, const char *id, uint32_t duration)
static void amxp_scheduler_remove_signal(amxp_scheduler_t *scheduler, const char *signal, const char *id)
static void amxp_scheduler_reset_timer(amxp_scheduler_t *scheduler)
static void amxp_schedule_item_delete(amxc_llist_it_t *it)
static void amxp_scheduler_add_signal(amxp_scheduler_t *scheduler, const char *signal, const char *id)
static void amxp_scheduler_trigger(amxp_timer_t *timer, void *priv)
static void amxp_scheduler_check_item(amxp_scheduler_t *scheduler, amxp_scheduler_item_t *item)
static void amxp_scheduler_item_stop(UNUSED amxp_timer_t *timer, void *priv)
static void amxp_scheduler_emit(amxp_scheduler_t *scheduler, amxp_scheduler_item_t *item, const char *signal, uint32_t duration, bool trigger)
static int amxp_scheduler_compare_items(amxc_llist_it_t *it1, amxc_llist_it_t *it2)
Ambiorix scheduler.
#define UNUSED
Definition: main.c:68
int amxp_cron_build_weekly(amxp_cron_expr_t *target, const char *time, const char *days_of_week)
Builds a weekly cron expression that is triggered at a certain time on certain days of the week.
Definition: amxp_cron.c:531
int64_t amxp_cron_time_until_next(const amxp_cron_expr_t *expr, bool local)
Calculates the time in seconds until next trigger of a parsed cron expression occurs.
Definition: amxp_cron.c:673
int amxp_cron_parse_expr(amxp_cron_expr_t *target, const char *expression, const char **error)
Allocates and initializes an amxp_cron_expr_t structures and parses the given cron expression.
Definition: amxp_cron.c:486
void amxp_cron_clean(amxp_cron_expr_t *cron_expr)
Resets the amxp_cron_expr_t structure to the initialized state.
Definition: amxp_cron.c:477
int amxp_cron_prev(const amxp_cron_expr_t *expr, const amxc_ts_t *ref, amxc_ts_t *next)
Calculates the previous trigger time for a parsed cron expression.
Definition: amxp_cron.c:588
int amxp_cron_next(const amxp_cron_expr_t *expr, const amxc_ts_t *ref, amxc_ts_t *next)
Calculates the next trigger time for a parsed cron expression.
Definition: amxp_cron.c:631
int amxp_scheduler_connect(amxp_scheduler_t *scheduler, const char *id, amxp_slot_fn_t fn, void *priv)
Connects a callback function to the scheduler.
int amxp_scheduler_use_local_time(amxp_scheduler_t *scheduler, bool use_local_time)
Use local time or UTC time in calculation for next trigger times.
int amxp_scheduler_set_weekly_begin_end_item(amxp_scheduler_t *scheduler, const char *id, const char *start_time, const char *end_time, const char *days_of_week)
Adds a schedule item or updates a schedule item using a start time, end time and list of week days.
int amxp_scheduler_enable_item(amxp_scheduler_t *scheduler, const char *id, bool enable)
Enables or disable a schedule item.
int amxp_scheduler_new(amxp_scheduler_t **scheduler)
Allocates a amxp_scheduler_t structures and initializes to an empty scheduler.
int amxp_scheduler_set_weekly_item(amxp_scheduler_t *scheduler, const char *id, const char *time, const char *days_of_week, uint32_t duration)
Adds a schedule item or updates a schedule item using a time and list of week days.
void amxp_scheduler_delete(amxp_scheduler_t **scheduler)
Frees the previously allocated amxp_scheduler_t structure.
int amxp_scheduler_disconnect(amxp_scheduler_t *scheduler, const char *id, amxp_slot_fn_t fn)
Disconnects a callback function from the scheduler.
int amxp_scheduler_remove_item(amxp_scheduler_t *scheduler, const char *id)
Removes a schedule item from the scheduler.
amxp_signal_mngr_t * amxp_scheduler_get_sigmngr(amxp_scheduler_t *scheduler)
Gets the signal manager of a scheduler.
int amxp_scheduler_enable(amxp_scheduler_t *scheduler, bool enable)
Enables or disable the scheduler.
int amxp_scheduler_set_cron_begin_end_item(amxp_scheduler_t *scheduler, const char *id, const char *cron_begin, const char *cron_end)
Adds a schedule item or updates a schedule item using a cron expressions.
int amxp_scheduler_set_cron_item(amxp_scheduler_t *scheduler, const char *id, const char *cron_expr, uint32_t duration)
Adds a schedule item or updates a schedule item using a cron expression.
int amxp_scheduler_init(amxp_scheduler_t *scheduler)
Initializes a amxp_scheduler_t to an empty scheduler.
int amxp_scheduler_update(amxp_scheduler_t *scheduler)
Forces recalculation of the schedule items' next occurrence time.
void amxp_scheduler_clean(amxp_scheduler_t *scheduler)
Cleans the scheduler.
int amxp_sigmngr_add_signal(amxp_signal_mngr_t *const sig_mngr, const char *name)
Adds a signal to a signal manager.
Definition: amxp_signal.c:433
int amxp_sigmngr_init(amxp_signal_mngr_t *sig_mngr)
Initializing function, initializes members of the amxp_signal_mngr_t structure.
Definition: amxp_signal.c:377
int amxp_sigmngr_clean(amxp_signal_mngr_t *sig_mngr)
Clean-up functions, cleans-up all members of a amxp_signal_mngr_t structure.
Definition: amxp_signal.c:405
void amxp_sigmngr_trigger_signal(amxp_signal_mngr_t *const sig_mngr, const char *name, const amxc_var_t *const data)
Triggers a signal.
Definition: amxp_signal.c:492
int amxp_sigmngr_remove_signal(amxp_signal_mngr_t *const sig_mngr, const char *name)
Removes a signal from a signal manager.
Definition: amxp_signal.c:448
amxp_signal_t * amxp_sigmngr_find_signal(const amxp_signal_mngr_t *const sig_mngr, const char *name)
Get the pointer to the signal.
Definition: amxp_signal.c:475
int amxp_sigmngr_enable(amxp_signal_mngr_t *const sig_mngr, bool enable)
Enables or disables the signal manager.
Definition: amxp_signal.c:561
int amxp_signal_delete(amxp_signal_t **signal)
Destructor function, deletes a signal.
Definition: amxp_signal.c:669
int amxp_sigmngr_emit_signal(const amxp_signal_mngr_t *const sig_mngr, const char *name, const amxc_var_t *const data)
Emits a signal.
Definition: amxp_signal.c:514
void amxp_slot_disconnect_all(amxp_slot_fn_t fn)
Disconnects a slot from all signals it was connected to.
Definition: amxp_slot.c:459
int amxp_slot_disconnect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, amxp_slot_fn_t fn)
Disconnects a slot from (a) signal(s).
Definition: amxp_slot.c:380
void(* amxp_slot_fn_t)(const char *const sig_name, const amxc_var_t *const data, void *const priv)
Slot callback function signature.
Definition: amxp_slot.h:93
int amxp_slot_connect(amxp_signal_mngr_t *const sig_mngr, const char *const sig_name, const char *const expression, amxp_slot_fn_t fn, void *const priv)
Connects a slot (function) to a named signal of a signal manager.
Definition: amxp_slot.c:300
int amxp_timer_start(amxp_timer_t *timer, unsigned int timeout_msec)
Starts or resets a timer.
Definition: amxp_timer.c:296
int amxp_timer_stop(amxp_timer_t *timer)
Stops the timer.
Definition: amxp_timer.c:319
void amxp_timer_delete(amxp_timer_t **timer)
Deletes a timer.
Definition: amxp_timer.c:247
int amxp_timer_new(amxp_timer_t **timer, amxp_timer_cb_t cb, void *priv)
Allocate and initializes a new timer.
Definition: amxp_timer.c:229
@ amxp_timer_running
Definition: amxp_timer.h:151
Structure containing the signal manager information.
Definition: amxp_signal.h:103
Structure containing the signal information.
Definition: amxp_signal.h:119
The timer type.
Definition: amxp_timer.h:163
amxp_timer_state_t state
Definition: amxp_timer.h:166
Structure containing a schedule item.
amxp_cron_expr_t end_cron
amxc_llist_it_t lit
amxp_cron_expr_t cron
amxc_htable_it_t hit
amxp_timer_t * timer
Structure containing a scheduler.
amxc_htable_t items
amxp_signal_mngr_t sigmngr
amxp_timer_t * timer
bool use_local_time
amxc_llist_t ordered_items
static amxp_signal_mngr_t * sigmngr