Asterisk - The Open Source Telephony Project GIT-master-77d630f
sorcery.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2012 - 2013, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Sorcery Data Access Layer API
22 *
23 * \author Joshua Colp <jcolp@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/logger.h"
33#include "asterisk/sorcery.h"
34#include "asterisk/astobj2.h"
35#include "asterisk/format.h"
36#include "asterisk/format_cap.h"
37#include "asterisk/strings.h"
39#include "asterisk/netsock2.h"
40#include "asterisk/module.h"
42#include "asterisk/threadpool.h"
43#include "asterisk/json.h"
44#include "asterisk/vector.h"
45#include "asterisk/cli.h"
46
47/* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
48#undef open
49#undef close
50
51/*! \brief Number of buckets for wizards (should be prime for performance reasons) */
52#define WIZARD_BUCKETS 7
53
54/*! \brief Number of buckets for types (should be prime for performance reasons) */
55#define TYPE_BUCKETS 53
56
57/*! \brief Number of buckets for instances (should be prime for performance reasons) */
58#define INSTANCE_BUCKETS 17
59
60/*! \brief Number of buckets for object fields (should be prime for performance reasons) */
61#define OBJECT_FIELD_BUCKETS 29
62
63#define NOTIFY_GENERIC_OBSERVERS(container, type, callback, ...) ({ \
64 struct ao2_iterator i = ao2_iterator_init(container, 0); \
65 struct type *observer; \
66 ao2_rdlock(container); \
67 while ((observer = ao2_iterator_next(&i))) { \
68 if (observer->callbacks->callback) { \
69 observer->callbacks->callback(__VA_ARGS__); \
70 } \
71 ao2_cleanup(observer); \
72 } \
73 ao2_unlock(container); \
74 ao2_iterator_cleanup(&i); \
75})
76
77#define NOTIFY_GLOBAL_OBSERVERS(container, callback, ...) \
78 NOTIFY_GENERIC_OBSERVERS(container, sorcery_global_observer, callback, __VA_ARGS__)
79
80#define NOTIFY_INSTANCE_OBSERVERS(container, callback, ...) \
81 NOTIFY_GENERIC_OBSERVERS(container, sorcery_instance_observer, callback, __VA_ARGS__)
82
83#define NOTIFY_WIZARD_OBSERVERS(container, callback, ...) \
84 NOTIFY_GENERIC_OBSERVERS(container, sorcery_wizard_observer, callback, __VA_ARGS__)
85
86/*! \brief Thread pool for observers */
88
89/*! \brief Structure for an internal wizard instance */
91 /*!
92 * \brief Wizard interface itself
93 * \warning Callbacks must always be declared first in this structure
94 * so an ao2_ref on &callbacks will adjust the ref count on
95 * internal_wizard.
96 */
98
99 /*! \brief Observers */
101};
102
103/*! \brief Structure for a wizard instance which operates on objects */
105 /*! \brief Wizard interface itself */
107
108 /*! \brief Unique data for the wizard */
109 void *data;
110
111 /*! \brief Wizard is acting as an object cache */
112 unsigned int caching:1;
113
114 /*! \brief Wizard is read_only */
115 unsigned int read_only:1;
116
117 /*! \brief Wizard allows others of the same type */
118 unsigned int allow_duplicates:1;
119
120 /*! \brief Wizard arguments */
121 char wizard_args[0];
122};
123
124/*! \brief Interface for a sorcery object type wizards */
125AST_VECTOR_RW(ast_sorcery_object_wizards, struct ast_sorcery_object_wizard *);
126
127/*! \brief Structure for internal sorcery object information */
129 /*! \brief Unique identifier of this object */
130 char *id;
131
132 /*! \brief Type of object */
134
135 /*! \brief Optional object destructor */
137
138 /*! \brief Extended object fields */
140
141 /*! \brief Time that the object was created */
142 struct timeval created;
143
144 /*! \brief Whether this object has dynamic contents or not */
145 unsigned int has_dynamic_contents:1;
146};
147
148/*! \brief Structure for registered object type */
150 /*! \brief Unique name of the object type */
152
153 /*! \brief Optional transformation callback */
155
156 /*! \brief Optional object set apply callback */
158
159 /*! \brief Optional object copy callback */
161
162 /*! \brief Optional object diff callback */
164
165 /*! \brief Wizard instances */
166 struct ast_sorcery_object_wizards wizards;
167
168 /*! \brief Object fields */
170
171 /*! \brief Configuration framework general information */
172 struct aco_info *info;
173
174 /*! \brief Configuration framework file information */
175 struct aco_file *file;
176
177 /*! \brief Type details */
179
180 /*! \brief Observers */
182
183 /*! \brief Serializer for observers */
185
186 /*! \brief Specifies if object type is reloadable or not */
187 unsigned int reloadable:1;
188};
189
190/*! \brief Structure for registered object type observer */
192 /*! \brief Pointer to the observer implementation */
194};
195
196/*! \brief Structure used for observer invocations */
198 /*! \brief Pointer to the object type */
200
201 /*! \brief Pointer to the object */
202 void *object;
203};
204
205/*! \brief Structure for registered object field */
207 /*! \brief Name of the field */
209
210 /*! \brief The compiled name regex if name is a regex */
211 regex_t *name_regex;
212
213 /*! \brief Callback function for translation of a single value */
215
216 /*! \brief Callback function for translation of multiple values */
218
219 /*! \brief Position of the field */
220 intptr_t args[];
221};
222
223/*! \brief Proxy object for sorcery */
226 /*! \brief The name of the module owning this sorcery instance */
227 char module_name[0];
228};
229
230/*! \brief Full structure for sorcery */
232 /*! \brief Container for known object types */
234
235 /*! \brief Observers */
237
238 /*! \brief Pointer to module_name in the associated sorcery_proxy. */
240};
241
242/*! \brief Structure for passing load/reload details */
244 /*! \brief Sorcery structure in use */
245 const struct ast_sorcery *sorcery;
246
247 /*! \brief Type of object being loaded */
248 const char *type;
249
250 /*! \brief Whether this is a reload or not */
251 unsigned int reload:1;
252
253 /*! \brief Whether this is forced or not */
254 unsigned int force:1;
255};
256
257/*! \brief Registered sorcery wizards */
258static struct ao2_container *wizards;
259
260/* The following 3 observer wrappers must name their
261 * external observer 'callbacks' and it must be
262 * the first member of the structure. Common macros
263 * and container callbacks depend on it.
264 */
265
266/*! \brief A global observer wrapper */
269};
270
271/*! \brief An instance observer wrapper */
274};
275
276/*! \brief A wizard observer wrapper */
279};
280
281/*! \brief Registered global observers */
283
284/*! \brief Registered sorcery instances */
286
287/* \brief Global config flag (declared in sorcery.h) */
289
290static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
291{
292 int *field = (int *)(obj + args[0]);
293 return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
294}
295
296static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
297{
298 unsigned int *field = (unsigned int *)(obj + args[0]);
299 return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
300}
301
302static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
303{
304 double *field = (double *)(obj + args[0]);
305 return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
306}
307
308static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
309{
310 ast_string_field *field = (const char **)(obj + args[0]);
311 return !(*buf = ast_strdup(*field)) ? -1 : 0;
312}
313
314static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
315{
316 unsigned int *field = (unsigned int *)(obj + args[0]);
317 return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
318}
319
320static int yesno_handler_fn(const void *obj, const intptr_t *args, char **buf)
321{
322 unsigned int *field = (unsigned int *)(obj + args[0]);
323 return !(*buf = ast_strdup(*field ? "yes" : "no")) ? -1 : 0;
324}
325
326static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
327{
328 struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
329 return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
330}
331
332static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
333{
334 char *field = (char *)(obj + args[0]);
335 return !(*buf = ast_strdup(field)) ? -1 : 0;
336}
337
338static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
339{
341 struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
342 return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
343}
344
346{
347 switch(type) {
348 case OPT_BOOL_T: return bool_handler_fn;
349 case OPT_YESNO_T: return yesno_handler_fn;
351 case OPT_CODEC_T: return codec_handler_fn;
352 case OPT_DOUBLE_T: return double_handler_fn;
353 case OPT_INT_T: return int_handler_fn;
356 case OPT_UINT_T: return uint_handler_fn;
357
358 default:
359 case OPT_CUSTOM_T: return NULL;
360 }
361
362 return NULL;
363}
364
365/*! \brief Hashing and comparison functions for sorcery wizards */
368
371
372/*!
373 * \internal
374 * \brief CLI command implementation for 'sorcery show settings'
375 */
376static char *cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
377{
378 switch (cmd) {
379 case CLI_INIT:
380 e->command = "sorcery show settings";
381 e->usage = "Usage: sorcery show settings\n"
382 " Show global configuration options\n";
383 return NULL;
384 case CLI_GENERATE:
385 return NULL;
386 }
387
388 ast_cli(a->fd, "\nSorcery global settings\n");
389 ast_cli(a->fd, "-----------------\n");
390 ast_cli(a->fd, " Update->Create fallback in backends: %s\n",
391 ast_sorcery_update_or_create_on_update_miss ? "enabled" : "disabled");
392
393 return CLI_SUCCESS;
394}
395
396
397static struct ast_cli_entry cli_commands[] = {
398 AST_CLI_DEFINE(cli_show_settings, "Show global configuration options"),
399};
400
401/*! \brief Cleanup function for graceful shutdowns */
402static void sorcery_cleanup(void)
403{
408 wizards = NULL;
410 observers = NULL;
412 instances = NULL;
413}
414
415/*! \brief Compare function for sorcery instances */
417
418/*! \brief Hashing function for sorcery instances */
420
421/*!
422 * \internal
423 * \brief Parse [general] options from sorcery.conf and set globals.
424 */
425static void parse_general_options(void)
426{
427 struct ast_flags flags = { 0 };
428 struct ast_config *cfg = ast_config_load2("sorcery.conf", "sorcery", flags);
429 const struct ast_variable *var;
430
431 if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
432 return;
433 }
434
435 for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
436 if (!strcasecmp(var->name, "update_or_create_on_update_miss")) {
438 }
439 }
440
442}
443
445{
448 .auto_increment = 1,
449 .max_size = 0,
450 .idle_timeout = 60,
451 .initial_size = 0,
452 };
454
456
458 if (!threadpool) {
459 return -1;
460 }
461
463 ast_sorcery_internal_wizard_hash_fn, NULL, ast_sorcery_internal_wizard_cmp_fn);
464 if (!wizards) {
465 return -1;
466 }
467
469 if (!observers) {
470 return -1;
471 }
472
474 sorcery_proxy_hash_fn, NULL, sorcery_proxy_cmp_fn);
475 if (!instances) {
476 return -1;
477 }
478
480 return -1;
481 }
482
484
485 return 0;
486}
487
489{
490 struct ast_sorcery_internal_wizard *wizard = obj;
491
492 ao2_cleanup(wizard->observers);
493}
494
495int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
496{
497 struct ast_sorcery_internal_wizard *wizard;
498 int res = -1;
499
500 ast_assert(!ast_strlen_zero(interface->name));
501
503
504 if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
505 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
506 interface->name);
507 goto done;
508 }
509
510 if (!(wizard = ao2_alloc(sizeof(*wizard), sorcery_internal_wizard_destructor))) {
511 goto done;
512 }
513
514 wizard->callbacks = *interface;
515 wizard->callbacks.module = module;
516
518 if (!wizard->observers) {
519 goto done;
520 }
521
523 res = 0;
524
525 ast_verb(5, "Sorcery registered wizard '%s'\n", interface->name);
526
527 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_registered,
528 interface->name, interface);
529
530done:
531 ao2_cleanup(wizard);
533
534 return res;
535}
536
538{
539 struct ast_sorcery_internal_wizard *wizard =
540 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL;
541
542 if (wizard) {
543 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_unregistering, wizard->callbacks.name, &wizard->callbacks);
544 ao2_unlink(wizards, wizard);
545 ao2_ref(wizard, -1);
546 ast_verb(5, "Sorcery unregistered wizard '%s'\n", interface->name);
547 return 0;
548 } else {
549 return -1;
550 }
551}
552
553/*! \brief Internal callback function for removing a generic observer */
554static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
555{
556 const struct sorcery_global_observer *observer = obj;
557
558 return (observer->callbacks == arg) ? CMP_MATCH : 0;
559}
560
562{
563 struct sorcery_global_observer *cb;
564
565 cb = ao2_alloc(sizeof(*cb), NULL);
566 if (!cb) {
567 return -1;
568 }
569
570 cb->callbacks = callbacks;
571 ao2_link(observers, cb);
572 ao2_ref(cb, -1);
573
574 return 0;
575}
576
579{
581}
582
585{
586 struct sorcery_instance_observer *cb;
587
588 cb = ao2_alloc(sizeof(*cb), NULL);
589 if (!cb) {
590 return -1;
591 }
592
593 cb->callbacks = callbacks;
595 ao2_ref(cb, -1);
596
597 return 0;
598}
599
602{
604}
605
608{
609 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
610 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
612
613 if (wizard) {
614 struct sorcery_wizard_observer *cb;
615
616 cb = ao2_alloc(sizeof(*cb), NULL);
617 if (!cb) {
618 return -1;
619 }
620
621 cb->callbacks = callbacks;
622 ao2_link(wizard->observers, cb);
623 ao2_ref(cb, -1);
624
625 return 0;
626 }
627
628 return -1;
629}
630
633{
634 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
635 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
637
638 if (wizard) {
640 }
641}
642
643/*! \brief Destructor called when sorcery structure is destroyed */
644static void sorcery_destructor(void *obj)
645{
646 struct ast_sorcery *sorcery = obj;
647
648 if (sorcery->observers) {
650 }
653}
654
655/*! \brief Hashing function for sorcery types */
658
659static void sorcery_proxy_cb(void *weakproxy, void *data)
660{
661 ao2_unlink(instances, weakproxy);
662}
663
664struct ast_sorcery *__ast_sorcery_open(const char *module_name, const char *file, int line, const char *func)
665{
666 struct sorcery_proxy *proxy;
667 struct ast_sorcery *sorcery;
668
670
673 __PRETTY_FUNCTION__, file, line, func);
674 if (sorcery) {
676
677 return sorcery;
678 }
679
680 proxy = ao2_t_weakproxy_alloc(sizeof(*proxy) + strlen(module_name) + 1, NULL, module_name);
681 if (!proxy) {
682 goto failure_cleanup;
683 }
684 strcpy(proxy->module_name, module_name); /* Safe */
685
687 if (!sorcery) {
688 goto failure_cleanup;
689 }
690
692
693 /* We have exclusive access to proxy and sorcery, no need for locking here. */
694 if (ao2_t_weakproxy_set_object(proxy, sorcery, OBJ_NOLOCK, "weakproxy link")) {
695 goto failure_cleanup;
696 }
697
699 goto failure_cleanup;
700 }
701
703 ast_sorcery_object_type_hash_fn, NULL, ast_sorcery_object_type_cmp_fn);
704 if (!sorcery->types) {
705 goto failure_cleanup;
706 }
707
709 goto failure_cleanup;
710 }
711
713 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
714 goto failure_cleanup;
715 }
716
718 ao2_ref(proxy, -1);
719
721
723 return sorcery;
724
725failure_cleanup:
726 /* cleanup of sorcery may result in locking instances, so make sure we unlock first. */
729 ao2_cleanup(proxy);
730
731 return NULL;
732}
733
734/*! \brief Search function for sorcery instances */
736{
738}
739
740/*! \brief Destructor function for object types */
741static void sorcery_object_type_destructor(void *obj)
742{
743 struct ast_sorcery_object_type *object_type = obj;
744
745 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
747 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
748 AST_VECTOR_RW_FREE(&object_type->wizards);
749 ao2_cleanup(object_type->fields);
750 ao2_cleanup(object_type->observers);
751
752 if (object_type->info) {
753 aco_info_destroy(object_type->info);
754 ast_free(object_type->info);
755 }
756
757 ast_free(object_type->file);
758
760}
761
762/*! \brief Internal function which allocates an object type structure */
763static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
764{
765#define INITIAL_WIZARD_VECTOR_SIZE 5
766 struct ast_sorcery_object_type *object_type;
767 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
768
769 if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
770 return NULL;
771 }
772
773 /* Order matters for object wizards */
774 if (AST_VECTOR_RW_INIT(&object_type->wizards, INITIAL_WIZARD_VECTOR_SIZE) != 0) {
775 ao2_ref(object_type, -1);
776 return NULL;
777 }
778
780 OBJECT_FIELD_BUCKETS, ast_sorcery_object_field_hash_fn, NULL, ast_sorcery_object_field_cmp_fn);
781 if (!object_type->fields) {
782 ao2_ref(object_type, -1);
783 return NULL;
784 }
785
787 NULL, NULL);
788 if (!object_type->observers) {
789 ao2_ref(object_type, -1);
790 return NULL;
791 }
792
793 object_type->info = ast_calloc(1,
794 sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0]));
795 if (!object_type->info) {
796 ao2_ref(object_type, -1);
797 return NULL;
798 }
799
800 object_type->file = ast_calloc(1,
801 sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0]));
802 if (!object_type->file) {
803 ao2_ref(object_type, -1);
804 return NULL;
805 }
806
807 /* Create name with seq number appended. */
808 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "sorcery/%s", type);
809
810 if (!(object_type->serializer = ast_threadpool_serializer(tps_name, threadpool))) {
811 ao2_ref(object_type, -1);
812 return NULL;
813 }
814
815 object_type->info->files[0] = object_type->file;
816 object_type->info->files[1] = NULL;
817 object_type->info->module = module;
818
819 ast_copy_string(object_type->name, type, sizeof(object_type->name));
820
821 return object_type;
822}
823
824/*! \brief Object wizard destructor */
826{
827 struct ast_sorcery_object_wizard *object_wizard = obj;
828
829 if (object_wizard->data && object_wizard->wizard->callbacks.close) {
830 object_wizard->wizard->callbacks.close(object_wizard->data);
831 }
832
833 if (object_wizard->wizard) {
834 ast_module_unref(object_wizard->wizard->callbacks.module);
835 }
836
837 ao2_cleanup(object_wizard->wizard);
838}
839
840/*! \brief Return the number of wizards mapped to an object type */
842 const char *type)
843{
845
846 if (!object_type) {
847 return -1;
848 }
849
850 return AST_VECTOR_SIZE(&object_type->wizards);
851}
852
854 const char *type, int index, struct ast_sorcery_wizard **wizard, void **data)
855{
857 struct ast_sorcery_object_wizard *owizard;
858
859 if (!object_type) {
860 return -1;
861 }
862
863 if (index < 0 || index >= AST_VECTOR_SIZE(&object_type->wizards)) {
864 return -1;
865 }
866
867 owizard = AST_VECTOR_GET(&object_type->wizards, index);
868
869 if (wizard != NULL) {
870 *wizard = &(owizard->wizard->callbacks);
871 ao2_bump(owizard->wizard);
872 } else {
873 return -1;
874 }
875
876 if (data != NULL) {
877 *data = owizard->data;
878 }
879
880 return 0;
881}
882
884 const char *object_type_name, const char *module, const char *wizard_type_name,
885 const char *wizard_args)
886{
887 RAII_VAR(struct ast_sorcery_object_type *, object_type,
888 ao2_find(sorcery->types, object_type_name, OBJ_SEARCH_KEY), ao2_cleanup);
889 int res = -1;
890 int i;
891
892 if (!object_type) {
893 return res;
894 }
895
896 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
897 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
898 struct ast_sorcery_object_wizard *wizard = AST_VECTOR_GET(&object_type->wizards, i);
899
900 if (strcmp(wizard->wizard->callbacks.name, wizard_type_name) == 0
901 && strcmp(S_OR(wizard->wizard_args, ""), S_OR(wizard_args, "")) == 0) {
902 ao2_cleanup(AST_VECTOR_REMOVE_ORDERED(&object_type->wizards, i));
903 res = 0;
904 break;
905 }
906 }
907 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
908
909 return res;
910}
911
912/*! \brief Internal function removes a wizard mapping */
914 const char *type, const char *module, const char *name)
915{
917 int res;
918
919 if (!object_type) {
920 return -1;
921 }
922
923 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
924#define WIZARD_NAME_COMPARE(a, b) (strcmp((a)->wizard->callbacks.name, (b)) == 0)
926#undef WIZARD_NAME_COMPARE
927 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
928
929 return res;
930}
931
933 const char *object_type_name, const char *module, const char *wizard_type_name,
934 const char *wizard_args, enum ast_sorcery_wizard_apply_flags flags, int position,
935 struct ast_sorcery_wizard **wizard, void **wizard_data)
936{
937 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, object_type_name, OBJ_KEY), ao2_cleanup);
938 RAII_VAR(struct ast_sorcery_internal_wizard *, internal_wizard, ao2_find(wizards, wizard_type_name, OBJ_KEY), ao2_cleanup);
939 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
940 int created = 0;
941
942 object_wizard = ao2_alloc(sizeof(*object_wizard)
943 + (ast_strlen_zero(wizard_args) ? 0 : strlen(wizard_args) + 1),
945
946 if (!object_wizard) {
948 }
949
950 if (!internal_wizard
951 || internal_wizard->callbacks.module != ast_module_running_ref(internal_wizard->callbacks.module)) {
953 "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
954 wizard_type_name, object_type_name);
956 }
957
958 if (!object_type) {
959 if (!(object_type = sorcery_object_type_alloc(object_type_name, module))) {
960 ast_module_unref(internal_wizard->callbacks.module);
962 }
963 created = 1;
964 }
965
966 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
967 if (!created) {
968 struct ast_sorcery_object_wizard *found;
969
970#define WIZARD_COMPARE(a, b) ((a)->wizard == (b))
971 found = AST_VECTOR_GET_CMP(&object_type->wizards, internal_wizard, WIZARD_COMPARE);
972#undef WIZARD_COMPARE
973 if (found
975 ast_debug(1, "Wizard %s already applied to object type %s\n",
976 internal_wizard->callbacks.name, object_type->name);
977 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
978 ast_module_unref(internal_wizard->callbacks.module);
980 }
981 }
982
983 ast_debug(5, "Calling wizard %s open callback on object type %s\n",
984 wizard_type_name, object_type->name);
985 if (internal_wizard->callbacks.open && !(object_wizard->data = internal_wizard->callbacks.open(wizard_args))) {
986 ast_log(LOG_WARNING, "Wizard '%s' failed to open mapping for object type '%s' with data: %s\n",
987 wizard_type_name, object_type->name, S_OR(wizard_args, ""));
988 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
989 ast_module_unref(internal_wizard->callbacks.module);
991 }
992
993 object_wizard->wizard = ao2_bump(internal_wizard);
994 object_wizard->caching = !!(flags & AST_SORCERY_WIZARD_APPLY_CACHING);
995 object_wizard->read_only = !!(flags & AST_SORCERY_WIZARD_APPLY_READONLY);
996 if (wizard_args) {
997 strcpy(object_wizard->wizard_args, wizard_args); /* Safe */
998 }
999
1000 if (position == AST_SORCERY_WIZARD_POSITION_LAST) {
1001 position = AST_VECTOR_SIZE(&object_type->wizards);
1002 }
1003
1004 if (AST_VECTOR_INSERT_AT(&object_type->wizards, position, object_wizard) != 0) {
1005 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1007 }
1008 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1009 ao2_bump(object_wizard);
1010
1011 if (created) {
1012 ao2_link(sorcery->types, object_type);
1013 }
1014
1016 sorcery->module_name, sorcery, object_type_name, &internal_wizard->callbacks, wizard_args,
1017 object_wizard->data);
1018
1019 if (wizard) {
1020 *wizard = &internal_wizard->callbacks;
1021 }
1022 if (wizard_data) {
1023 *wizard_data = object_wizard->data;
1024 }
1025
1027}
1028
1029/*! \brief Internal function which creates an object type and inserts a wizard mapping */
1031 const char *type, const char *module, const char *name,
1032 const char *data, unsigned int caching, int position)
1033{
1036 position, NULL, NULL);
1037}
1038
1039/*! \brief Internal function which creates an object type and adds a wizard mapping */
1041 const char *type, const char *module, const char *name,
1042 const char *data, unsigned int caching)
1043{
1046}
1047
1049{
1050 struct ast_flags flags = { 0 };
1051 struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
1052 struct ast_variable *mapping;
1053 int res = AST_SORCERY_APPLY_SUCCESS;
1054
1055 if (!config) {
1057 }
1058
1061 }
1062
1063 for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
1064 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
1065 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
1066 char *options = mapping_name;
1067 char *type = strsep(&options, "/");
1068 char *data = mapping_value;
1069 char *wizard = strsep(&data, ",");
1070 unsigned int caching = 0;
1071
1072 /* If no object type or wizard exists just skip, nothing we can do */
1073 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
1074 continue;
1075 }
1076
1077 /* If the wizard is configured as a cache treat it as such */
1078 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
1079 caching = 1;
1080 }
1081
1082 /* Any error immediately causes us to stop */
1083 if (__ast_sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
1085 break;
1086 }
1087 }
1088
1090
1091 return res;
1092}
1093
1094enum ast_sorcery_apply_result __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
1095{
1097
1098 /* Defaults can not be added if any existing mapping exists */
1099 if (object_type) {
1101 }
1102
1103 return __ast_sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
1104}
1105
1106static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1107{
1108 return ast_sorcery_object_set_extended(obj, var->name, var->value);
1109}
1110
1111static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
1112{
1113 const struct ast_sorcery_object_details *details = obj;
1114
1115 if (details->object->extended) {
1116 *fields = ast_variables_dup(details->object->extended);
1117 } else {
1118 *fields = NULL;
1119 }
1120
1121 return 0;
1122}
1123
1125{
1126 struct ast_sorcery_object_type *object_type;
1127 int res = -1;
1128
1130 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1131 if (object_type && object_type->type.type == ACO_ITEM) {
1132 ao2_unlink_flags(sorcery->types, object_type, OBJ_NOLOCK);
1133 res = 0;
1134 }
1136
1137 /* XXX may need to add an instance unregister observer callback on success. */
1138
1139 ao2_cleanup(object_type);
1140 return res;
1141}
1142
1144{
1146
1147 if (!object_type || object_type->type.item_alloc) {
1148 return -1;
1149 }
1150
1151 object_type->type.name = object_type->name;
1152 object_type->type.type = ACO_ITEM;
1153 object_type->type.category = ".?";
1154 object_type->type.item_alloc = alloc;
1155 object_type->type.hidden = hidden;
1156
1157 object_type->reloadable = reloadable;
1158 object_type->transform = transform;
1159 object_type->apply = apply;
1160 object_type->file->types[0] = &object_type->type;
1161 object_type->file->types[1] = NULL;
1162
1163 if (aco_info_init(object_type->info)) {
1164 return -1;
1165 }
1166
1168 return -1;
1169 }
1170
1171 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, object_type_registered,
1173
1174 return 0;
1175}
1176
1177int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water)
1178{
1179 struct ast_sorcery_object_type *object_type;
1180 int res = -1;
1181
1182 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1183 if (object_type) {
1185 low_water, high_water);
1186 ao2_ref(object_type, -1);
1187 }
1188 return res;
1189}
1190
1192{
1194
1195 if (!object_type) {
1196 return;
1197 }
1198
1199 object_type->copy = copy;
1200}
1201
1203{
1205
1206 if (!object_type) {
1207 return;
1208 }
1209
1210 object_type->diff = diff;
1211}
1212
1214{
1215 struct ast_sorcery_object_field *object_field = obj;
1216
1217 if (object_field->name_regex) {
1218 regfree(object_field->name_regex);
1219 ast_free(object_field->name_regex);
1220 }
1221}
1222
1223int ast_sorcery_object_fields_register(struct ast_sorcery *sorcery, const char *type, const char *regex, aco_option_handler config_handler, sorcery_fields_handler sorcery_handler)
1224{
1225#define MAX_REGEX_ERROR_LEN 128
1227 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1228 int rc;
1229
1230 if (!object_type || !object_type->type.item_alloc || !config_handler
1231 || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
1232 return -1;
1233 }
1234
1235 ast_copy_string(object_field->name, regex, sizeof(object_field->name));
1236 object_field->multiple_handler = sorcery_handler;
1237
1238 if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
1239 return -1;
1240 }
1241
1242 if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
1243 char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
1244 regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
1245 ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
1246 return -1;
1247 }
1248
1249 ao2_link(object_type->fields, object_field);
1250 __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
1251
1252 return 0;
1253}
1254
1255int __ast_sorcery_object_field_register(struct ast_sorcery *sorcery, const char *type, const char *name, const char *default_val, enum aco_option_type opt_type,
1256 aco_option_handler config_handler, sorcery_field_handler sorcery_handler, sorcery_fields_handler multiple_handler, unsigned int flags, unsigned int no_doc, unsigned int alias, size_t argc, ...)
1257{
1259 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1260 int pos;
1261 va_list args;
1262
1263 if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
1264 return -1;
1265 }
1266
1267 if (!sorcery_handler) {
1268 sorcery_handler = sorcery_field_default_handler(opt_type);
1269 }
1270
1271 if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
1272 return -1;
1273 }
1274
1275 ast_copy_string(object_field->name, name, sizeof(object_field->name));
1276 object_field->handler = sorcery_handler;
1277 object_field->multiple_handler = multiple_handler;
1278
1279 va_start(args, argc);
1280 for (pos = 0; pos < argc; pos++) {
1281 object_field->args[pos] = va_arg(args, size_t);
1282 }
1283 va_end(args);
1284
1285 if (!alias) {
1286 ao2_link(object_type->fields, object_field);
1287 }
1288
1289 /* TODO: Improve this hack */
1290 if (!argc) {
1291 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
1292 } else if (argc == 1) {
1293 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1294 object_field->args[0]);
1295 } else if (argc == 2) {
1296 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1297 object_field->args[0], object_field->args[1]);
1298 } else if (argc == 3) {
1299 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1300 object_field->args[0], object_field->args[1], object_field->args[2]);
1301 } else {
1302 ast_assert(0); /* The hack... she does us no good for this */
1303 }
1304
1305 return 0;
1306}
1307
1308/*! \brief Retrieves whether or not the type is reloadable */
1309static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
1310{
1311 RAII_VAR(struct ast_sorcery_object_type *, object_type,
1313 return object_type && object_type->reloadable;
1314}
1315
1316static int sorcery_wizard_load(void *obj, void *arg, int flags)
1317{
1318 struct ast_sorcery_object_wizard *wizard = obj;
1319 struct sorcery_load_details *details = arg;
1320 void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
1321
1322 if (details->reload) {
1323 if (details->force && wizard->wizard->callbacks.force_reload) {
1324 load = wizard->wizard->callbacks.force_reload;
1325 } else {
1326 load = wizard->wizard->callbacks.reload;
1327 }
1328 } else {
1329 load = wizard->wizard->callbacks.load;
1330 }
1331
1332 if (load) {
1333 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
1334 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1335
1336 load(wizard->data, details->sorcery, details->type);
1337
1338 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loaded,
1339 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1340 }
1341
1342 return 0;
1343}
1344
1345/*! \brief Destructor for observer invocation */
1347{
1348 struct sorcery_observer_invocation *invocation = obj;
1349
1350 ao2_cleanup(invocation->object_type);
1351 ao2_cleanup(invocation->object);
1352}
1353
1354/*! \brief Allocator function for observer invocation */
1356{
1357 struct sorcery_observer_invocation *invocation;
1358
1359 invocation = ao2_alloc_options(sizeof(*invocation),
1361 if (!invocation) {
1362 return NULL;
1363 }
1364
1365 ao2_ref(object_type, +1);
1366 invocation->object_type = object_type;
1367
1368 if (object) {
1369 ao2_ref(object, +1);
1370 invocation->object = object;
1371 }
1372
1373 return invocation;
1374}
1375
1376/*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1377static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1378{
1379 const struct ast_sorcery_object_type_observer *observer = obj;
1380
1381 if (observer->callbacks->loaded) {
1382 observer->callbacks->loaded(arg);
1383 }
1384
1385 return 0;
1386}
1387
1388/*! \brief Internal callback function which notifies observers that an object type has been loaded */
1390{
1391 struct sorcery_observer_invocation *invocation = data;
1392
1394 ao2_cleanup(invocation);
1395
1396 return 0;
1397}
1398
1399static int sorcery_object_load(void *obj, void *arg, int flags)
1400{
1401 struct ast_sorcery_object_type *type = obj;
1402 struct sorcery_load_details *details = arg;
1403
1404 if (!type->type.item_alloc) {
1405 return 0;
1406 }
1407
1408 details->type = type->name;
1409
1410 if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
1411 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
1412 details->type);
1413 return 0;
1414 }
1415
1416 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
1417 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1418
1419 AST_VECTOR_RW_RDLOCK(&type->wizards);
1420 AST_VECTOR_CALLBACK(&type->wizards, sorcery_wizard_load, NULL, details, 0);
1421 AST_VECTOR_RW_UNLOCK(&type->wizards);
1422
1423 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
1424 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1425
1426 if (ao2_container_count(type->observers)) {
1427 struct sorcery_observer_invocation *invocation;
1428
1430 if (invocation
1432 invocation)) {
1433 ao2_cleanup(invocation);
1434 }
1435 }
1436
1437 return 0;
1438}
1439
1441{
1442 struct sorcery_load_details details = {
1443 .sorcery = sorcery,
1444 .reload = 0,
1445 };
1446
1447 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1449
1451
1454}
1455
1456void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1457{
1459 struct sorcery_load_details details = {
1460 .sorcery = sorcery,
1461 .reload = 0,
1462 };
1463
1464 if (!object_type) {
1465 return;
1466 }
1467
1468 sorcery_object_load(object_type, &details, 0);
1469}
1470
1472{
1473 struct sorcery_load_details details = {
1474 .sorcery = sorcery,
1475 .reload = 1,
1476 };
1477
1478 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1480
1482
1485
1486}
1487
1489{
1490 struct sorcery_load_details details = {
1491 .sorcery = sorcery,
1492 .reload = 1,
1493 .force = 1,
1494 };
1495
1496 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1498
1500
1503}
1504
1505void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1506{
1508 struct sorcery_load_details details = {
1509 .sorcery = sorcery,
1510 .reload = 1,
1511 };
1512
1513 if (!object_type) {
1514 return;
1515 }
1516
1517 sorcery_object_load(object_type, &details, 0);
1518}
1519
1521{
1523 struct sorcery_load_details details = {
1524 .sorcery = sorcery,
1525 .reload = 1,
1526 .force = 1,
1527 };
1528
1529 if (!object_type) {
1530 return;
1531 }
1532
1533 sorcery_object_load(object_type, &details, 0);
1534}
1535
1537{
1538 ao2_ref(sorcery, +1);
1539}
1540
1541static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1542{
1543 struct ast_variable *tmp = NULL;
1544 char *buf = NULL;
1545
1546 if (!object_field->handler) {
1547 return NULL;
1548 }
1549
1550 if (!(object_field->handler(object, object_field->args, &buf))) {
1551 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1552 }
1553 ast_free(buf);
1554
1555 return tmp;
1556}
1557
1558static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1559{
1560 struct ast_variable *tmp = NULL;
1561
1562 if (!object_field->multiple_handler) {
1563 return NULL;
1564 }
1565
1566 if (object_field->multiple_handler(object, &tmp)) {
1568 tmp = NULL;
1569 }
1570
1571 return tmp;
1572}
1573
1575 const void *object, enum ast_sorcery_field_handler_flags flags)
1576{
1577 const struct ast_sorcery_object_details *details = object;
1578 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1579 struct ao2_iterator i;
1580 struct ast_sorcery_object_field *object_field;
1581 struct ast_variable *head = NULL;
1582 struct ast_variable *tail = NULL;
1583
1584 if (!object_type) {
1585 return NULL;
1586 }
1587
1588 i = ao2_iterator_init(object_type->fields, 0);
1589
1590 for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1591 struct ast_variable *tmp;
1592
1593 switch (flags) {
1595 if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1596 (tmp = get_single_field_as_var_list(object, object_field))) {
1597 break;
1598 }
1599 continue;
1601 if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1602 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1603 break;
1604 }
1605 continue;
1607 if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1608 break;
1609 }
1610 continue;
1612 if ((tmp = get_single_field_as_var_list(object, object_field))) {
1613 break;
1614 }
1615 continue;
1616 default:
1617 continue;
1618 }
1619
1620 tail = ast_variable_list_append_hint(&head, tail, tmp);
1621 }
1622
1624
1625 return head;
1626}
1627
1628struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1629{
1630 const struct ast_sorcery_object_details *details = object;
1631 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1632 struct ao2_iterator i;
1633 struct ast_sorcery_object_field *object_field;
1634 struct ast_json *json = ast_json_object_create();
1635 int res = 0;
1636
1637 if (!object_type || !json) {
1638 ast_json_unref(json);
1639 return NULL;
1640 }
1641
1642 i = ao2_iterator_init(object_type->fields, 0);
1643
1644 for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1645 if (object_field->multiple_handler) {
1646 struct ast_variable *tmp = NULL;
1647 struct ast_variable *field;
1648
1649 if ((res = object_field->multiple_handler(object, &tmp))) {
1651 ao2_ref(object_field, -1);
1652 break;
1653 }
1654
1655 for (field = tmp; field; field = field->next) {
1656 struct ast_json *value = ast_json_string_create(field->value);
1657
1658 if (!value || ast_json_object_set(json, field->name, value)) {
1659 res = -1;
1660 break;
1661 }
1662 }
1663
1665 } else if (object_field->handler) {
1666 char *buf = NULL;
1667 struct ast_json *value = NULL;
1668
1669 if (object_field->handler(object, object_field->args, &buf)
1671 || ast_json_object_set(json, object_field->name, value)) {
1672 ast_free(buf);
1673 ast_debug(5, "Skipping field '%s' for object type '%s'\n",
1674 object_field->name, object_type->name);
1675 continue;
1676 }
1677
1678 ast_free(buf);
1679 } else {
1680 continue;
1681 }
1682 }
1683
1685
1686 /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1687 if (res) {
1688 ast_json_unref(json);
1689 json = NULL;
1690 }
1691
1692 return json;
1693}
1694
1695int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1696{
1697 const struct ast_sorcery_object_details *details = object;
1698 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1699 RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1700 struct ast_variable *field;
1701 int res = 0;
1702
1703 if (!object_type) {
1704 return -1;
1705 }
1706
1707 if (object_type->transform && (transformed = object_type->transform(objectset))) {
1708 field = transformed;
1709 } else {
1710 field = objectset;
1711 }
1712
1713 for (; field; field = field->next) {
1714 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1715 break;
1716 }
1717 }
1718
1719 if (!res && object_type->apply) {
1720 res = object_type->apply(sorcery, object);
1721 }
1722
1723 return res;
1724}
1725
1726int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1727{
1728 const struct ast_variable *field;
1729 int res = 0;
1730
1731 *changes = NULL;
1732
1733 /* Unless the ast_variable list changes when examined... it can't differ from itself */
1734 if (original == modified) {
1735 return 0;
1736 }
1737
1738 for (field = modified; field; field = field->next) {
1739 const char *old_value = ast_variable_find_in_list(original, field->name);
1740
1741 if (!old_value || strcmp(old_value, field->value)) {
1742 struct ast_variable *tmp;
1743
1744 if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1745 res = -1;
1746 break;
1747 }
1748
1749 tmp->next = *changes;
1750 *changes = tmp;
1751 }
1752 }
1753
1754 /* If an error occurred do not return a partial changeset */
1755 if (res) {
1756 ast_variables_destroy(*changes);
1757 *changes = NULL;
1758 }
1759
1760 return res;
1761}
1762
1763static void sorcery_object_destructor(void *object)
1764{
1765 struct ast_sorcery_object_details *details = object;
1766
1767 if (details->object->destructor) {
1768 details->object->destructor(object);
1769 }
1770
1772 ast_free(details->object->id);
1773}
1774
1775void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
1776{
1777 void *object = ao2_alloc_with_lockobj(size + sizeof(struct ast_sorcery_object),
1778 sorcery_object_destructor, lockobj, "");
1779 struct ast_sorcery_object_details *details = object;
1780
1781 if (!object) {
1782 return NULL;
1783 }
1784
1785 details->object = object + size;
1786 details->object->destructor = destructor;
1787
1788 return object;
1789}
1790
1791void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1792{
1793 void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object),
1795 struct ast_sorcery_object_details *details = object;
1796
1797 if (!object) {
1798 return NULL;
1799 }
1800
1801 details->object = object + size;
1802 details->object->destructor = destructor;
1803
1804 return object;
1805}
1806
1807void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1808{
1810 struct ast_sorcery_object_details *details;
1811
1812 if (!object_type || !object_type->type.item_alloc ||
1813 !(details = object_type->type.item_alloc(id))) {
1814 return NULL;
1815 }
1816
1817 if (ast_strlen_zero(id)) {
1818 char uuid[AST_UUID_STR_LEN];
1819
1821 details->object->id = ast_strdup(uuid);
1822 } else {
1823 details->object->id = ast_strdup(id);
1824 }
1825 if (!details->object->id) {
1826 ao2_ref(details, -1);
1827 return NULL;
1828 }
1829
1830 details->object->created = ast_tvnow();
1831 ast_copy_string(details->object->type, type, sizeof(details->object->type));
1832
1833 if (aco_set_defaults(&object_type->type, id, details)) {
1834 ao2_ref(details, -1);
1835 return NULL;
1836 }
1837
1838 return details;
1839}
1840
1841void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1842{
1843 const struct ast_sorcery_object_details *details = object;
1844 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1846 RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1847 int res = 0;
1848
1849 if (!copy) {
1850 return NULL;
1851 } else if (object_type->copy) {
1852 res = object_type->copy(object, copy);
1853 } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1854 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1855 } else {
1856 /* No native copy available and could not create an objectset, this copy has failed */
1857 res = -1;
1858 }
1859
1860 if (res) {
1862 copy = NULL;
1863 }
1864
1865 return copy;
1866}
1867
1868int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1869{
1871
1872 *changes = NULL;
1873
1874 if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1875 return -1;
1876 }
1877
1878 if (original == modified) {
1879 return 0;
1880 } else if (!object_type->diff) {
1881 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1882 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1883
1884 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1885 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1886
1887 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1888 } else {
1889 return object_type->diff(original, modified, changes);
1890 }
1891}
1892
1893/*! \brief Structure used when calling create, update, or delete */
1895 /*! \brief Pointer to the sorcery instance */
1896 const struct ast_sorcery *sorcery;
1897 /*! \brief Pointer to the object itself */
1898 void *obj;
1899};
1900
1901/*! \brief Internal function used to create an object in caching wizards */
1902static int sorcery_cache_create(void *obj, void *arg, int flags)
1903{
1904 const struct ast_sorcery_object_wizard *object_wizard = obj;
1905 const struct sorcery_details *details = arg;
1906
1907 if (!object_wizard->caching || !object_wizard->wizard->callbacks.create) {
1908 return 0;
1909 }
1910
1911 object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj);
1912
1913 return 0;
1914}
1915
1916void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1917{
1918 struct ast_sorcery_object_type *object_type;
1919 void *object = NULL;
1920 int i;
1921 unsigned int cached = 0;
1922
1923 if (ast_strlen_zero(id)) {
1924 return NULL;
1925 }
1926
1927 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1928 if (!object_type) {
1929 return NULL;
1930 }
1931
1932 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
1933 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
1935 AST_VECTOR_GET(&object_type->wizards, i);
1936
1937 if (wizard->wizard->callbacks.retrieve_id &&
1938 !(object = wizard->wizard->callbacks.retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1939 continue;
1940 }
1941
1942 cached = wizard->caching;
1943 break;
1944 }
1945
1946 if (!cached && object) {
1947 struct sorcery_details sdetails = {
1948 .sorcery = sorcery,
1949 .obj = object,
1950 };
1951
1952 AST_VECTOR_CALLBACK(&object_type->wizards, sorcery_cache_create, NULL, &sdetails, 0);
1953 }
1954 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1955
1956 ao2_ref(object_type, -1);
1957 return object;
1958}
1959
1960void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1961{
1963 void *object = NULL;
1964 int i;
1965 unsigned int cached = 0;
1966
1967 if (!object_type) {
1968 return NULL;
1969 }
1970
1971 /* If returning multiple objects create a container to store them in */
1972 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1974 if (!object) {
1975 return NULL;
1976 }
1977 }
1978
1979 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
1980 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
1982 AST_VECTOR_GET(&object_type->wizards, i);
1983
1984 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1985 if (wizard->wizard->callbacks.retrieve_multiple) {
1986 wizard->wizard->callbacks.retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1987 }
1988 } else if (fields && wizard->wizard->callbacks.retrieve_fields) {
1989 if (wizard->wizard->callbacks.retrieve_fields) {
1990 object = wizard->wizard->callbacks.retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1991 }
1992 }
1993
1994 if (((flags & AST_RETRIEVE_FLAG_MULTIPLE) && (!ao2_container_count(object) || !wizard->caching)) || !object) {
1995 continue;
1996 }
1997
1998 cached = wizard->caching;
1999
2000 break;
2001 }
2002
2003 /* If we are returning a single object and it came from a non-cache source create it in any caches */
2004 if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
2005 struct sorcery_details sdetails = {
2006 .sorcery = sorcery,
2007 .obj = object,
2008 };
2009
2010 AST_VECTOR_CALLBACK(&object_type->wizards, sorcery_cache_create, NULL, &sdetails, 0);
2011 }
2012 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2013
2014 return object;
2015}
2016
2017struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
2018{
2020 struct ao2_container *objects;
2021 int i;
2022
2023 if (!object_type) {
2024 return NULL;
2025 }
2026
2028 if (!objects) {
2029 return NULL;
2030 }
2031
2032 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2033 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2035 AST_VECTOR_GET(&object_type->wizards, i);
2036
2037 if (!wizard->wizard->callbacks.retrieve_regex) {
2038 continue;
2039 }
2040
2041 wizard->wizard->callbacks.retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
2042
2043 if (wizard->caching && ao2_container_count(objects)) {
2044 break;
2045 }
2046 }
2047 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2048
2049 return objects;
2050}
2051
2052struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
2053{
2055 struct ao2_container *objects;
2056 int i;
2057
2058 if (!object_type) {
2059 return NULL;
2060 }
2061
2063 if (!objects) {
2064 return NULL;
2065 }
2066
2067 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2068 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2070 AST_VECTOR_GET(&object_type->wizards, i);
2071
2072 if (!wizard->wizard->callbacks.retrieve_prefix) {
2073 continue;
2074 }
2075
2076 wizard->wizard->callbacks.retrieve_prefix(sorcery, wizard->data, object_type->name, objects, prefix, prefix_len);
2077
2078 if (wizard->caching && ao2_container_count(objects)) {
2079 break;
2080 }
2081 }
2082 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2083
2084 return objects;
2085}
2086
2087/*! \brief Internal function which returns if the wizard has created the object */
2088static int sorcery_wizard_create(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2089{
2090 if (!object_wizard->wizard->callbacks.create || object_wizard->read_only) {
2091 ast_debug(5, "Sorcery wizard '%s' does not support creation\n", object_wizard->wizard->callbacks.name);
2092 return 0;
2093 }
2094
2095 if (object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) {
2096 return 0;
2097 }
2098
2099 return CMP_MATCH;
2100}
2101
2102/*! \brief Internal callback function which notifies an individual observer that an object has been created */
2103static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
2104{
2105 const struct ast_sorcery_object_type_observer *observer = obj;
2106
2107 if (observer->callbacks->created) {
2108 observer->callbacks->created(arg);
2109 }
2110
2111 return 0;
2112}
2113
2114/*! \brief Internal callback function which notifies observers that an object has been created */
2116{
2117 struct sorcery_observer_invocation *invocation = data;
2118
2120 ao2_cleanup(invocation);
2121
2122 return 0;
2123}
2124
2125int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
2126{
2127 const struct ast_sorcery_object_details *details = object;
2128 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2129 struct ast_sorcery_object_wizard *object_wizard = NULL;
2130 struct ast_sorcery_object_wizard *found_wizard;
2131 int i;
2132 struct sorcery_details sdetails = {
2133 .sorcery = sorcery,
2134 .obj = object,
2135 };
2136
2137 if (!object_type) {
2138 return -1;
2139 }
2140
2141 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2142 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2143 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2144 if (!found_wizard->caching
2145 && sorcery_wizard_create(found_wizard, &sdetails) == CMP_MATCH) {
2146 object_wizard = found_wizard;
2147 }
2148 }
2149
2150 if (object_wizard) {
2151 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2152 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2153 if (found_wizard->caching) {
2154 sorcery_wizard_create(found_wizard, &sdetails);
2155 }
2156 }
2157
2158 if (ao2_container_count(object_type->observers)) {
2159 struct sorcery_observer_invocation *invocation;
2160
2161 invocation = sorcery_observer_invocation_alloc(object_type, object);
2162 if (invocation
2164 invocation)) {
2165 ao2_cleanup(invocation);
2166 }
2167 }
2168 }
2169
2171
2172 return object_wizard ? 0 : -1;
2173}
2174
2175/*! \brief Internal callback function which notifies an individual observer that an object has been updated */
2176static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
2177{
2178 const struct ast_sorcery_object_type_observer *observer = obj;
2179
2180 if (observer->callbacks->updated) {
2181 observer->callbacks->updated(arg);
2182 }
2183
2184 return 0;
2185}
2186
2187/*! \brief Internal callback function which notifies observers that an object has been updated */
2189{
2190 struct sorcery_observer_invocation *invocation = data;
2191
2193 ao2_cleanup(invocation);
2194
2195 return 0;
2196}
2197
2198/*! \brief Internal function which returns if a wizard has updated the object */
2199static int sorcery_wizard_update(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2200{
2201 if (!object_wizard->wizard->callbacks.update || object_wizard->read_only) {
2202 ast_debug(5, "Sorcery wizard '%s' does not support updating\n", object_wizard->wizard->callbacks.name);
2203 return 0;
2204 }
2205
2206 if (object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj)) {
2207 return 0;
2208 }
2209
2210 return CMP_MATCH;
2211}
2212
2213int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
2214{
2215 const struct ast_sorcery_object_details *details = object;
2216 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2217 struct ast_sorcery_object_wizard *object_wizard = NULL;
2218 struct ast_sorcery_object_wizard *found_wizard;
2219 int i;
2220 struct sorcery_details sdetails = {
2221 .sorcery = sorcery,
2222 .obj = object,
2223 };
2224
2225 if (!object_type) {
2226 return -1;
2227 }
2228
2229 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2230 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2231 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2232 if (!found_wizard->caching
2233 && sorcery_wizard_update(found_wizard, &sdetails) == CMP_MATCH) {
2234 object_wizard = found_wizard;
2235 }
2236 }
2237
2238 if (object_wizard) {
2239 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2240 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2241 if (found_wizard->caching) {
2242 sorcery_wizard_update(found_wizard, &sdetails);
2243 }
2244 }
2245
2246 if (ao2_container_count(object_type->observers)) {
2247 struct sorcery_observer_invocation *invocation;
2248
2249 invocation = sorcery_observer_invocation_alloc(object_type, object);
2250 if (invocation
2252 invocation)) {
2253 ao2_cleanup(invocation);
2254 }
2255 }
2256 }
2257
2259
2260 return object_wizard ? 0 : -1;
2261}
2262
2263/*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
2264static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
2265{
2266 const struct ast_sorcery_object_type_observer *observer = obj;
2267
2268 if (observer->callbacks->deleted) {
2269 observer->callbacks->deleted(arg);
2270 }
2271
2272 return 0;
2273}
2274
2275/*! \brief Internal callback function which notifies observers that an object has been deleted */
2277{
2278 struct sorcery_observer_invocation *invocation = data;
2279
2281 ao2_cleanup(invocation);
2282
2283 return 0;
2284}
2285
2286/*! \brief Internal function which returns if a wizard has deleted the object */
2287static int sorcery_wizard_delete(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2288{
2289 if (!object_wizard->wizard->callbacks.delete || object_wizard->read_only) {
2290 ast_debug(5, "Sorcery wizard '%s' does not support deletion\n", object_wizard->wizard->callbacks.name);
2291 return 0;
2292 }
2293
2294 if (object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj)) {
2295 return 0;
2296 }
2297
2298 return CMP_MATCH;
2299}
2300
2301int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
2302{
2303 const struct ast_sorcery_object_details *details = object;
2304 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2305 struct ast_sorcery_object_wizard *object_wizard = NULL;
2306 struct ast_sorcery_object_wizard *found_wizard;
2307 int i;
2308 struct sorcery_details sdetails = {
2309 .sorcery = sorcery,
2310 .obj = object,
2311 };
2312
2313 if (!object_type) {
2314 return -1;
2315 }
2316
2317 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2318 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2319 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2320 if (!found_wizard->caching
2321 && sorcery_wizard_delete(found_wizard, &sdetails) == CMP_MATCH) {
2322 object_wizard = found_wizard;
2323 }
2324 }
2325
2326 if (object_wizard) {
2327 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2328 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2329 if (found_wizard->caching) {
2330 sorcery_wizard_delete(found_wizard, &sdetails);
2331 }
2332 }
2333
2334 if (ao2_container_count(object_type->observers)) {
2335 struct sorcery_observer_invocation *invocation;
2336
2337 invocation = sorcery_observer_invocation_alloc(object_type, object);
2338 if (invocation
2340 invocation)) {
2341 ao2_cleanup(invocation);
2342 }
2343 }
2344 }
2345
2347
2348 return object_wizard ? 0 : -1;
2349}
2350
2351int ast_sorcery_is_stale(const struct ast_sorcery *sorcery, void *object)
2352{
2353 const struct ast_sorcery_object_details *details = object;
2354 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2355 struct ast_sorcery_object_wizard *found_wizard;
2356 int res = 0;
2357 int i;
2358
2359 if (!object_type) {
2360 return -1;
2361 }
2362
2363 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2364 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2365 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2366
2367 if (found_wizard->wizard->callbacks.is_stale) {
2368 res |= found_wizard->wizard->callbacks.is_stale(sorcery, found_wizard->data, object);
2369 ast_debug(5, "After calling wizard '%s', object '%s' is %s\n",
2370 found_wizard->wizard->callbacks.name,
2372 res ? "stale" : "not stale");
2373 }
2374 }
2375 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2376
2377 return res;
2378}
2379
2380const char *ast_sorcery_object_get_id(const void *object)
2381{
2382 const struct ast_sorcery_object_details *details = object;
2383 return details->object->id;
2384}
2385
2386const struct timeval ast_sorcery_object_get_created(const void *object)
2387{
2388 const struct ast_sorcery_object_details *details = object;
2389 return details->object->created;
2390}
2391
2392const char *ast_sorcery_object_get_type(const void *object)
2393{
2394 const struct ast_sorcery_object_details *details = object;
2395 return details->object->type;
2396}
2397
2398const char *ast_sorcery_object_get_extended(const void *object, const char *name)
2399{
2400 const struct ast_sorcery_object_details *details = object;
2401 struct ast_variable *field;
2402
2403 for (field = details->object->extended; field; field = field->next) {
2404 if (!strcmp(field->name + 1, name)) {
2405 return field->value;
2406 }
2407 }
2408
2409 return NULL;
2410}
2411
2412int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
2413{
2415 struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
2416 const struct ast_sorcery_object_details *details = object;
2417
2418 if (!extended) {
2419 return -1;
2420 }
2421
2422 for (field = details->object->extended; field; previous = field, field = field->next) {
2423 if (!strcmp(field->name, name)) {
2424 if (previous) {
2425 previous->next = field->next;
2426 } else {
2427 details->object->extended = field->next;
2428 }
2429 field->next = NULL;
2430 break;
2431 }
2432 }
2433
2434 extended->next = details->object->extended;
2435 details->object->extended = extended;
2436
2437 return 0;
2438}
2439
2440unsigned int ast_sorcery_object_has_dynamic_contents(const void *object)
2441{
2442 const struct ast_sorcery_object_details *details = object;
2443
2444 return details->object->has_dynamic_contents;
2445}
2446
2448{
2449 const struct ast_sorcery_object_details *details = object;
2450
2451 details->object->has_dynamic_contents = 1;
2452}
2453
2455{
2458 int res;
2459
2460 if (!object_type || !callbacks) {
2461 return -1;
2462 }
2463
2464 if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
2465 return -1;
2466 }
2467
2468 observer->callbacks = callbacks;
2469 res = 0;
2470 if (!ao2_link(object_type->observers, observer)) {
2471 res = -1;
2472 }
2473 ao2_ref(observer, -1);
2474
2475 return res;
2476}
2477
2478/*! \brief Internal callback function for removing an observer */
2479static int sorcery_observer_remove(void *obj, void *arg, int flags)
2480{
2481 const struct ast_sorcery_object_type_observer *observer = obj;
2482
2483 return (observer->callbacks == arg) ? CMP_MATCH : 0;
2484}
2485
2487{
2488 RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
2489 struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
2490
2491 if (!sorcery) {
2492 return;
2493 }
2494 object_type = ao2_find(sorcery->types, type, OBJ_KEY);
2495 if (!object_type) {
2496 return;
2497 }
2498
2499 ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
2501}
2502
2503int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
2504{
2505 const void *object_left = obj;
2506 const void *object_right = arg;
2507 const char *right_key = arg;
2508 int cmp;
2509
2510 switch (flags & OBJ_SEARCH_MASK) {
2511 case OBJ_SEARCH_OBJECT:
2512 right_key = ast_sorcery_object_get_id(object_right);
2513 /* Fall through */
2514 case OBJ_SEARCH_KEY:
2515 cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
2516 break;
2518 cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
2519 break;
2520 default:
2521 cmp = 0;
2522 break;
2523 }
2524 return cmp;
2525}
2526
2527int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
2528{
2529 int cmp;
2530
2531 cmp = ast_sorcery_object_id_sort(obj, arg, flags);
2532 if (cmp) {
2533 return 0;
2534 }
2535 return CMP_MATCH;
2536}
2537
2538int ast_sorcery_object_id_hash(const void *obj, int flags)
2539{
2540 const char *key;
2541
2542 switch (flags & OBJ_SEARCH_MASK) {
2543 case OBJ_SEARCH_KEY:
2544 key = obj;
2545 break;
2546 case OBJ_SEARCH_OBJECT:
2547 key = ast_sorcery_object_get_id(obj);
2548 break;
2549 default:
2550 /* Hash can only work on something with a full key. */
2551 ast_assert(0);
2552 return 0;
2553 }
2554 return ast_str_hash(key);
2555}
2556
2558 const char *type)
2559{
2561}
2562
2563static int is_registered_cb(void *obj, void *arg, int flags)
2564{
2565 struct ast_sorcery_object_field *object_field = obj;
2566 char *name = arg;
2567 int rc = 0;
2568
2569 if (object_field->name_regex
2570 && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
2571 rc = CMP_MATCH;
2572 }
2573
2574 return rc;
2575}
2576
2578 const char *field_name)
2579{
2580 struct ast_sorcery_object_field *object_field;
2581 int res = 1;
2582
2583 ast_assert(object_type != NULL);
2584
2585 object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
2586
2587 if (!object_field) {
2588 object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
2589 }
2590
2591 if (!object_field) {
2592 res = 0;
2593 }
2594
2595 ao2_cleanup(object_field);
2596 return res;
2597}
2598
2600{
2601 return sorcery->module_name;
2602}
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define var
Definition: ast_expr2f.c:605
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
Request notification when weakproxy points to NULL.
Definition: astobj2.c:934
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
#define OBJ_KEY
Definition: astobj2.h:1151
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:365
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_wrlock(a)
Definition: astobj2.h:719
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
Definition: astobj2.h:2048
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_unlink_flags(container, obj, flags)
Remove an object from a container.
Definition: astobj2.h:1600
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Definition: astobj2.h:1554
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
Definition: astobj2.h:358
#define ao2_alloc_with_lockobj(data_size, destructor_fn, lockobj, tag)
Allocate and initialize an object with separate locking.
Definition: astobj2.h:431
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_t_weakproxy_alloc(data_size, destructor_fn, tag)
Definition: astobj2.h:553
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_weakproxy_find(c, arg, flags, tag)
Perform an ao2_find on a container with ao2_weakproxy objects, returning the real object.
Definition: astobj2.h:1748
#define ao2_lock(a)
Definition: astobj2.h:717
void * __ao2_weakproxy_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
Definition: astobj2.h:2032
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
Definition: astobj2.h:1116
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_SEARCH_MASK
Search option field mask.
Definition: astobj2.h:1072
@ OBJ_UNLINK
Definition: astobj2.h:1039
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a list container.
Definition: astobj2.h:1327
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
void * __ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result
Definition: astobj2.c:768
#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.
Definition: astobj2.h:1303
#define ao2_t_weakproxy_set_object(weakproxy, obj, flags, tag)
Definition: astobj2.h:582
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT
Reject objects with duplicate keys in container.
Definition: astobj2.h:1188
static const char type[]
Definition: chan_ooh323.c:109
static const char config[]
Definition: chan_ooh323.c:111
Standard Command Line Interface.
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Configuration option-handling.
int(* aco_option_handler)(const struct aco_option *opt, struct ast_variable *var, void *obj)
A callback function for handling a particular option.
@ ACO_EXACT
@ ACO_REGEX
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
aco_option_type
The option types.
@ OPT_UINT_T
Type for default option handler for unsigned integers.
@ OPT_CODEC_T
Type for default option handler for format capabilities.
@ OPT_BOOL_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_CUSTOM_T
Type for a custom (user-defined) option handler.
@ OPT_CHAR_ARRAY_T
Type for default option handler for character array strings.
@ OPT_SOCKADDR_T
Type for default handler for ast_sockaddrs.
@ OPT_YESNO_T
Type for default option handler for bools (ast_true/ast_false)
@ OPT_INT_T
Type for default option handler for signed integers.
@ OPT_DOUBLE_T
Type for default option handler for doubles.
@ OPT_STRINGFIELD_T
Type for default option handler for stringfields.
void *(* aco_type_item_alloc)(const char *category)
Allocate a configurable ao2 object.
@ ACO_ITEM
int aco_process_var(struct aco_type *type, const char *cat, struct ast_variable *var, void *obj)
Parse a single ast_variable and apply it to an object.
int __aco_option_register(struct aco_info *info, const char *name, enum aco_matchtype match_type, struct aco_type **types, const char *default_val, enum aco_option_type type, aco_option_handler handler, unsigned int flags, unsigned int no_doc, size_t argc,...)
register a config option
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Media Format API.
Format Capabilities API.
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
static const char name[]
Definition: format_mp3.c:68
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
static int uuid(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_uuid.c:52
static char prefix[MAX_PREFIX]
Definition: http.c:144
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
Definition: main/config.c:1013
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEINVALID
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
Definition: main/config.c:629
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1287
struct ast_variable * ast_variable_list_append_hint(struct ast_variable **head, struct ast_variable *search_hint, struct ast_variable *new_var)
Appends a variable list to the end of another list.
Definition: main/config.c:732
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1260
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1213
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
Asterisk JSON abstraction layer.
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
Definition: json.c:399
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
Definition: module.h:469
Network socket handling.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
static struct ast_sorcery * sorcery
struct ast_sorcery_instance_observer observer
struct @476 callbacks
#define NULL
Definition: resample.c:96
#define INSTANCE_BUCKETS
Number of buckets for instances (should be prime for performance reasons)
Definition: sorcery.c:58
const char * ast_sorcery_object_get_extended(const void *object, const char *name)
Get an extended field value from a sorcery object.
Definition: sorcery.c:2398
static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:290
static void parse_general_options(void)
Compare function for sorcery instances.
Definition: sorcery.c:425
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2380
static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
Internal callback function which notifies an individual observer that an object has been deleted.
Definition: sorcery.c:2264
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
Unregister a sorcery wizard.
Definition: sorcery.c:537
static int sorcery_observers_notify_create(void *data)
Internal callback function which notifies observers that an object has been created.
Definition: sorcery.c:2115
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Remove an observer from a specific object type.
Definition: sorcery.c:2486
static struct ast_cli_entry cli_commands[]
Definition: sorcery.c:397
int ast_sorcery_object_fields_register(struct ast_sorcery *sorcery, const char *type, const char *regex, aco_option_handler config_handler, sorcery_fields_handler sorcery_handler)
Register a regex for multiple fields within an object.
Definition: sorcery.c:1223
int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
Set an extended field value on a sorcery object.
Definition: sorcery.c:2412
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Remove an observer from a sorcery instance.
Definition: sorcery.c:600
#define WIZARD_NAME_COMPARE(a, b)
enum ast_sorcery_apply_result __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
Apply default object wizard mappings.
Definition: sorcery.c:1094
static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
Internal callback function which notifies an individual observer that an object has been updated.
Definition: sorcery.c:2176
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition: sorcery.c:1440
void ast_sorcery_wizard_observer_remove(struct ast_sorcery_wizard *interface, const struct ast_sorcery_wizard_observer *callbacks)
Remove an observer from a sorcery wizard.
Definition: sorcery.c:631
static int sorcery_cache_create(void *obj, void *arg, int flags)
Internal function used to create an object in caching wizards.
Definition: sorcery.c:1902
const char * ast_sorcery_get_module(const struct ast_sorcery *sorcery)
Get the module that has opened the provided sorcery instance.
Definition: sorcery.c:2599
static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:332
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2392
int ast_sorcery_update_or_create_on_update_miss
Global control for optional update->create fallback in backends.
Definition: sorcery.c:288
static int sorcery_observers_notify_delete(void *data)
Internal callback function which notifies observers that an object has been deleted.
Definition: sorcery.c:2276
#define NOTIFY_GLOBAL_OBSERVERS(container, callback,...)
Definition: sorcery.c:77
static void sorcery_destructor(void *obj)
Destructor called when sorcery structure is destroyed.
Definition: sorcery.c:644
#define INITIAL_WIZARD_VECTOR_SIZE
#define MAX_REGEX_ERROR_LEN
void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
Set the copy handler for an object type.
Definition: sorcery.c:1191
void ast_sorcery_object_set_has_dynamic_contents(const void *object)
Set the dynamic contents flag on a sorcery object.
Definition: sorcery.c:2447
static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:308
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2125
static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:338
struct ast_sorcery_object_type * ast_sorcery_get_object_type(const struct ast_sorcery *sorcery, const char *type)
Get the sorcery object type given a type name.
Definition: sorcery.c:2557
#define WIZARD_BUCKETS
Number of buckets for wizards (should be prime for performance reasons)
Definition: sorcery.c:52
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
Create a changeset of two objects.
Definition: sorcery.c:1868
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
Definition: sorcery.c:1916
AST_VECTOR_RW(ast_sorcery_object_wizards, struct ast_sorcery_object_wizard *)
Interface for a sorcery object type wizards.
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
Definition: sorcery.c:1471
int ast_sorcery_get_wizard_mapping_count(struct ast_sorcery *sorcery, const char *type)
Return the number of wizards mapped to an object type.
Definition: sorcery.c:841
struct ao2_container * ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
Retrieve multiple objects using a regular expression on their id.
Definition: sorcery.c:2017
int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
Register a sorcery wizard.
Definition: sorcery.c:495
static void sorcery_object_type_destructor(void *obj)
Destructor function for object types.
Definition: sorcery.c:741
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
Add an observer to a specific object type.
Definition: sorcery.c:2454
static int sorcery_observer_remove(void *obj, void *arg, int flags)
Internal callback function for removing an observer.
Definition: sorcery.c:2479
enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data, unsigned int caching, int position)
Internal function which creates an object type and inserts a wizard mapping.
Definition: sorcery.c:1030
static struct ast_threadpool * threadpool
Thread pool for observers.
Definition: sorcery.c:87
void ast_sorcery_force_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects, even if no changes determined.
Definition: sorcery.c:1488
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to load persistent objects.
Definition: sorcery.c:1456
static struct ast_variable * get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
Definition: sorcery.c:1541
#define WIZARD_COMPARE(a, b)
static struct ast_variable * get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
Definition: sorcery.c:1558
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1791
static int sorcery_wizard_load(void *obj, void *arg, int flags)
Definition: sorcery.c:1316
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
Definition: sorcery.c:1124
static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
Internal callback function for removing a generic observer.
Definition: sorcery.c:554
int __ast_sorcery_remove_wizard_mapping(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name)
Internal function removes a wizard mapping.
Definition: sorcery.c:913
static void sorcery_proxy_cb(void *weakproxy, void *data)
Hashing function for sorcery types.
Definition: sorcery.c:659
static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
Internal callback function which notifies an individual observer that an object type has been loaded.
Definition: sorcery.c:1377
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2527
static int yesno_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:320
static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:314
static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
Definition: sorcery.c:1111
unsigned int ast_sorcery_object_has_dynamic_contents(const void *object)
Get whether an object contains dynamic contents or not.
Definition: sorcery.c:2440
void ast_sorcery_ref(struct ast_sorcery *sorcery)
Increase the reference count of a sorcery structure.
Definition: sorcery.c:1536
static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:296
int __ast_sorcery_object_field_register(struct ast_sorcery *sorcery, const char *type, const char *name, const char *default_val, enum aco_option_type opt_type, aco_option_handler config_handler, sorcery_field_handler sorcery_handler, sorcery_fields_handler multiple_handler, unsigned int flags, unsigned int no_doc, unsigned int alias, size_t argc,...)
Register a field within an object.
Definition: sorcery.c:1255
int ast_sorcery_wizard_observer_add(struct ast_sorcery_wizard *interface, const struct ast_sorcery_wizard_observer *callbacks)
Add an observer to a sorcery wizard.
Definition: sorcery.c:606
static void sorcery_object_destructor(void *object)
Definition: sorcery.c:1763
int __ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, unsigned int hidden, unsigned int reloadable, aco_type_item_alloc alloc, sorcery_transform_handler transform, sorcery_apply_handler apply)
Register an object type.
Definition: sorcery.c:1143
static int sorcery_wizard_create(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
Internal function which returns if the wizard has created the object.
Definition: sorcery.c:2088
int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
Create a changeset given two object sets.
Definition: sorcery.c:1726
#define NOTIFY_INSTANCE_OBSERVERS(container, callback,...)
Definition: sorcery.c:80
static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
Retrieves whether or not the type is reloadable.
Definition: sorcery.c:1309
static char * cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Hashing and comparison functions for sorcery wizards.
Definition: sorcery.c:376
static int sorcery_object_load(void *obj, void *arg, int flags)
Definition: sorcery.c:1399
static struct ao2_container * wizards
Registered sorcery wizards.
Definition: sorcery.c:258
enum ast_sorcery_apply_result __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
Apply configured wizard mappings.
Definition: sorcery.c:1048
int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type, const char *field_name)
Determine if a particular object field has been registered with sorcery.
Definition: sorcery.c:2577
static struct ao2_container * instances
Registered sorcery instances.
Definition: sorcery.c:285
static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:326
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1807
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2503
const struct timeval ast_sorcery_object_get_created(const void *object)
Get when the sorcery object was created.
Definition: sorcery.c:2386
void * ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
Allocate a generic sorcery capable object with locking.
Definition: sorcery.c:1775
#define OBJECT_FIELD_BUCKETS
Number of buckets for object fields (should be prime for performance reasons)
Definition: sorcery.c:61
struct ao2_container * observers
Registered global observers.
Definition: sorcery.c:282
static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
Internal callback function which notifies an individual observer that an object has been created.
Definition: sorcery.c:2103
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2213
static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: sorcery.c:1106
int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
Apply an object set (KVP list) to an object.
Definition: sorcery.c:1695
int ast_sorcery_get_wizard_mapping(struct ast_sorcery *sorcery, const char *type, int index, struct ast_sorcery_wizard **wizard, void **data)
By index, return a wizard mapped to an object type.
Definition: sorcery.c:853
static int sorcery_wizard_update(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
Internal function which returns if a wizard has updated the object.
Definition: sorcery.c:2199
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects even if no changes determin...
Definition: sorcery.c:1520
static void sorcery_observer_invocation_destroy(void *obj)
Destructor for observer invocation.
Definition: sorcery.c:1346
static struct sorcery_observer_invocation * sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
Allocator function for observer invocation.
Definition: sorcery.c:1355
enum ast_sorcery_apply_result __ast_sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data, unsigned int caching)
Internal function which creates an object type and adds a wizard mapping.
Definition: sorcery.c:1040
int __ast_sorcery_object_type_remove_wizard(struct ast_sorcery *sorcery, const char *object_type_name, const char *module, const char *wizard_type_name, const char *wizard_args)
Remove an object wizard mapping.
Definition: sorcery.c:883
static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
Definition: sorcery.c:345
void ast_sorcery_global_observer_remove(const struct ast_sorcery_global_observer *callbacks)
Remove a global observer from sorcery.
Definition: sorcery.c:577
static int sorcery_wizard_delete(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
Internal function which returns if a wizard has deleted the object.
Definition: sorcery.c:2287
struct ast_json * ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
Create an object set in JSON format for an object.
Definition: sorcery.c:1628
static void sorcery_cleanup(void)
Cleanup function for graceful shutdowns.
Definition: sorcery.c:402
int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
Add a global observer to sorcery.
Definition: sorcery.c:561
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
Inform any wizards of a specific object type to reload persistent objects.
Definition: sorcery.c:1505
static int sorcery_observers_notify_update(void *data)
Internal callback function which notifies observers that an object has been updated.
Definition: sorcery.c:2188
#define NOTIFY_WIZARD_OBSERVERS(container, callback,...)
Definition: sorcery.c:83
struct ast_variable * ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery, const void *object, enum ast_sorcery_field_handler_flags flags)
Create an object set (KVP list) for an object.
Definition: sorcery.c:1574
int ast_sorcery_is_stale(const struct ast_sorcery *sorcery, void *object)
Determine if a sorcery object is stale with respect to its backing datastore.
Definition: sorcery.c:2351
int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery, const struct ast_sorcery_instance_observer *callbacks)
Add an observer to a sorcery instance.
Definition: sorcery.c:583
#define TYPE_BUCKETS
Number of buckets for types (should be prime for performance reasons)
Definition: sorcery.c:55
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2538
struct ast_sorcery * __ast_sorcery_open(const char *module_name, const char *file, int line, const char *func)
Definition: sorcery.c:664
static int sorcery_observers_notify_loaded(void *data)
Internal callback function which notifies observers that an object type has been loaded.
Definition: sorcery.c:1389
static int is_registered_cb(void *obj, void *arg, int flags)
Definition: sorcery.c:2563
void * ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
Retrieve an object or multiple objects using specific fields.
Definition: sorcery.c:1960
static void sorcery_object_field_destructor(void *obj)
Definition: sorcery.c:1213
static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:302
int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water)
Set the high and low alert water marks of the sorcery object type.
Definition: sorcery.c:1177
struct ast_sorcery * ast_sorcery_retrieve_by_module_name(const char *module_name)
Search function for sorcery instances.
Definition: sorcery.c:735
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Definition: sorcery.c:2301
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
Definition: sorcery.c:1841
struct ao2_container * ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
Retrieve multiple objects whose id begins with the specified prefix.
Definition: sorcery.c:2052
int ast_sorcery_init(void)
Initialize the sorcery API.
Definition: sorcery.c:444
static struct ast_sorcery_object_type * sorcery_object_type_alloc(const char *type, const char *module)
Internal function which allocates an object type structure.
Definition: sorcery.c:763
static void sorcery_object_wizard_destructor(void *obj)
Object wizard destructor.
Definition: sorcery.c:825
enum ast_sorcery_apply_result __ast_sorcery_object_type_insert_wizard(struct ast_sorcery *sorcery, const char *object_type_name, const char *module, const char *wizard_type_name, const char *wizard_args, enum ast_sorcery_wizard_apply_flags flags, int position, struct ast_sorcery_wizard **wizard, void **wizard_data)
Insert an additional object wizard mapping at a specific position in the wizard list returning wizard...
Definition: sorcery.c:932
static void sorcery_internal_wizard_destructor(void *obj)
Definition: sorcery.c:488
void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
Set the diff handler for an object type.
Definition: sorcery.c:1202
Sorcery Data Access Layer API.
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1137
struct ast_variable *(* sorcery_transform_handler)(struct ast_variable *set)
A callback function for performing a transformation on an object set.
Definition: sorcery.h:181
@ AST_RETRIEVE_FLAG_MULTIPLE
Return all matching objects.
Definition: sorcery.h:120
int(* sorcery_fields_handler)(const void *obj, struct ast_variable **fields)
A callback function for translating multiple values into an ast_variable list.
Definition: sorcery.h:169
int(* sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj)
A callback function for when an object set is successfully applied to an object.
Definition: sorcery.h:194
int(* sorcery_diff_handler)(const void *original, const void *modified, struct ast_variable **changes)
A callback function for generating a changeset between two objects.
Definition: sorcery.h:217
int(* sorcery_copy_handler)(const void *src, void *dst)
A callback function for copying the contents of one object to another.
Definition: sorcery.h:205
@ AST_SORCERY_WIZARD_POSITION_LAST
Definition: sorcery.h:518
ast_sorcery_field_handler_flags
Field handler flags.
Definition: sorcery.h:129
@ AST_HANDLER_PREFER_STRING
Try both handlers, string first.
Definition: sorcery.h:131
@ AST_HANDLER_PREFER_LIST
Try both handlers, list first.
Definition: sorcery.h:134
@ AST_HANDLER_ONLY_LIST
Use list handler only.
Definition: sorcery.h:140
@ AST_HANDLER_ONLY_STRING
Use string handler only.
Definition: sorcery.h:137
int(* sorcery_field_handler)(const void *obj, const intptr_t *args, char **buf)
A callback function for translating a value into a string.
Definition: sorcery.h:158
#define MAX_OBJECT_FIELD
Maximum length of an object field name.
Definition: sorcery.h:110
#define MAX_OBJECT_TYPE
Maximum size of an object type.
Definition: sorcery.h:107
ast_sorcery_wizard_apply_flags
Wizard Apply Flags.
Definition: sorcery.h:575
@ AST_SORCERY_WIZARD_APPLY_NONE
Definition: sorcery.h:577
@ AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE
Definition: sorcery.h:583
@ AST_SORCERY_WIZARD_APPLY_READONLY
Definition: sorcery.h:581
@ AST_SORCERY_WIZARD_APPLY_CACHING
Definition: sorcery.h:579
ast_sorcery_apply_result
Definition: sorcery.h:423
@ AST_SORCERY_APPLY_SUCCESS
Definition: sorcery.h:427
@ AST_SORCERY_APPLY_NO_CONFIGURATION
Definition: sorcery.h:433
@ AST_SORCERY_APPLY_FAIL
Definition: sorcery.h:425
@ AST_SORCERY_APPLY_DUPLICATE
Definition: sorcery.h:429
@ AST_SORCERY_APPLY_DEFAULT_UNNECESSARY
Definition: sorcery.h:431
const char * ast_string_field
Definition: stringfields.h:190
String manipulation functions.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
Definition: strings.h:1259
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2235
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_alloca(init_len)
Definition: strings.h:848
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
The representation of a single configuration file to be processed.
struct aco_type * types[]
struct aco_file * files[]
const char * module
Type information about a category-level configurable object.
enum aco_type_t type
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
descriptor for a cli entry.
Definition: cli.h:171
Structure used to handle boolean flags.
Definition: utils.h:217
unsigned int flags
Definition: utils.h:218
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Abstract JSON element (object, array, string, int, ...).
Socket address structure.
Definition: netsock2.h:97
Interface for the global sorcery observer.
Definition: sorcery.h:220
Interface for the sorcery instance observer.
Definition: sorcery.h:237
Structure for an internal wizard instance.
Definition: sorcery.c:90
struct ao2_container * observers
Observers.
Definition: sorcery.c:100
struct ast_sorcery_wizard callbacks
Wizard interface itself.
Definition: sorcery.c:97
Structure which contains details about a sorcery object.
Definition: sorcery.h:350
struct ast_sorcery_object * object
Pointer to internal sorcery object information.
Definition: sorcery.h:352
Structure for registered object field.
Definition: sorcery.c:206
regex_t * name_regex
The compiled name regex if name is a regex.
Definition: sorcery.c:211
sorcery_field_handler handler
Callback function for translation of a single value.
Definition: sorcery.c:214
sorcery_fields_handler multiple_handler
Callback function for translation of multiple values.
Definition: sorcery.c:217
intptr_t args[]
Position of the field.
Definition: sorcery.c:220
char name[MAX_OBJECT_FIELD]
Name of the field.
Definition: sorcery.c:208
Structure for registered object type observer.
Definition: sorcery.c:191
const struct ast_sorcery_observer * callbacks
Pointer to the observer implementation.
Definition: sorcery.c:193
Structure for registered object type.
Definition: sorcery.c:149
sorcery_copy_handler copy
Optional object copy callback.
Definition: sorcery.c:160
struct aco_file * file
Configuration framework file information.
Definition: sorcery.c:175
struct ast_sorcery_object_wizards wizards
Wizard instances.
Definition: sorcery.c:166
sorcery_transform_handler transform
Optional transformation callback.
Definition: sorcery.c:154
struct ao2_container * fields
Object fields.
Definition: sorcery.c:169
char name[MAX_OBJECT_TYPE]
Unique name of the object type.
Definition: sorcery.c:151
sorcery_diff_handler diff
Optional object diff callback.
Definition: sorcery.c:163
sorcery_apply_handler apply
Optional object set apply callback.
Definition: sorcery.c:157
struct ao2_container * observers
Observers.
Definition: sorcery.c:181
struct ast_taskprocessor * serializer
Serializer for observers.
Definition: sorcery.c:184
struct aco_type type
Type details.
Definition: sorcery.c:178
unsigned int reloadable
Specifies if object type is reloadable or not.
Definition: sorcery.c:187
struct aco_info * info
Configuration framework general information.
Definition: sorcery.c:172
Structure for a wizard instance which operates on objects.
Definition: sorcery.c:104
unsigned int caching
Wizard is acting as an object cache.
Definition: sorcery.c:112
struct ast_sorcery_internal_wizard * wizard
Wizard interface itself.
Definition: sorcery.c:106
void * data
Unique data for the wizard.
Definition: sorcery.c:109
unsigned int allow_duplicates
Wizard allows others of the same type.
Definition: sorcery.c:118
char wizard_args[0]
Wizard arguments.
Definition: sorcery.c:121
unsigned int read_only
Wizard is read_only.
Definition: sorcery.c:115
Structure for internal sorcery object information.
Definition: sorcery.c:128
unsigned int has_dynamic_contents
Whether this object has dynamic contents or not.
Definition: sorcery.c:145
struct timeval created
Time that the object was created.
Definition: sorcery.c:142
ao2_destructor_fn destructor
Optional object destructor.
Definition: sorcery.c:136
struct ast_variable * extended
Extended object fields.
Definition: sorcery.c:139
char type[MAX_OBJECT_TYPE]
Type of object.
Definition: sorcery.c:133
char * id
Unique identifier of this object.
Definition: sorcery.c:130
Interface for a sorcery object type observer.
Definition: sorcery.h:332
Interface for the sorcery wizard observer.
Definition: sorcery.h:265
Interface for a sorcery wizard.
Definition: sorcery.h:276
void(* close)(void *data)
Callback for closing a wizard.
Definition: sorcery.h:322
void(* retrieve_multiple)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
Optional callback for retrieving multiple objects using some optional field criteria.
Definition: sorcery.h:313
struct ast_module * module
Pointer to the Asterisk module this wizard is implemented by.
Definition: sorcery.h:281
void *(* retrieve_fields)(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields)
Optional callback for retrieving an object using fields.
Definition: sorcery.h:310
const char * name
Name of the wizard.
Definition: sorcery.h:278
void(* load)(void *data, const struct ast_sorcery *sorcery, const char *type)
Optional callback for loading persistent objects.
Definition: sorcery.h:287
void *(* retrieve_id)(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
Callback for retrieving an object using an id.
Definition: sorcery.h:296
int(* create)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for creating an object.
Definition: sorcery.h:293
int(* delete)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for deleting an object.
Definition: sorcery.h:319
int(* is_stale)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for whether or not the wizard believes the object is stale.
Definition: sorcery.h:325
void(* retrieve_prefix)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
Optional callback for retrieving multiple objects by matching their id with a prefix.
Definition: sorcery.h:302
void(* force_reload)(void *data, const struct ast_sorcery *sorcery, const char *type)
Optional callback for forcing a reload to occur, even if wizard has determined no changes.
Definition: sorcery.h:328
void(* retrieve_regex)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex)
Callback for retrieving multiple objects using a regex on their id.
Definition: sorcery.h:299
int(* update)(const struct ast_sorcery *sorcery, void *data, void *object)
Callback for updating an object.
Definition: sorcery.h:316
void(* reload)(void *data, const struct ast_sorcery *sorcery, const char *type)
Optional callback for reloading persistent objects.
Definition: sorcery.h:290
Full structure for sorcery.
Definition: sorcery.c:231
char * module_name
Pointer to module_name in the associated sorcery_proxy.
Definition: sorcery.c:239
struct ao2_container * observers
Observers.
Definition: sorcery.c:236
struct ao2_container * types
Container for known object types.
Definition: sorcery.c:233
Support for dynamic strings.
Definition: strings.h:623
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:69
An opaque threadpool structure.
Definition: threadpool.c:36
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Structure used when calling create, update, or delete.
Definition: sorcery.c:1894
void * obj
Pointer to the object itself.
Definition: sorcery.c:1898
const struct ast_sorcery * sorcery
Pointer to the sorcery instance.
Definition: sorcery.c:1896
A global observer wrapper.
Definition: sorcery.c:267
const struct ast_sorcery_global_observer * callbacks
Definition: sorcery.c:268
An instance observer wrapper.
Definition: sorcery.c:272
const struct ast_sorcery_instance_observer * callbacks
Definition: sorcery.c:273
Structure for passing load/reload details.
Definition: sorcery.c:243
unsigned int force
Whether this is forced or not.
Definition: sorcery.c:254
const char * type
Type of object being loaded.
Definition: sorcery.c:248
unsigned int reload
Whether this is a reload or not.
Definition: sorcery.c:251
const struct ast_sorcery * sorcery
Sorcery structure in use.
Definition: sorcery.c:245
Structure used for observer invocations.
Definition: sorcery.c:197
void * object
Pointer to the object.
Definition: sorcery.c:202
struct ast_sorcery_object_type * object_type
Pointer to the object type.
Definition: sorcery.c:199
Proxy object for sorcery.
Definition: sorcery.c:224
char module_name[0]
The name of the module owning this sorcery instance.
Definition: sorcery.c:227
A wizard observer wrapper.
Definition: sorcery.c:277
const struct ast_sorcery_wizard_observer * callbacks
Definition: sorcery.c:278
int value
Definition: syslog.c:37
An API for managing task processing threads that can be shared across modules.
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap) attribute_warn_unused_result
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
void ast_taskprocessor_build_name(char *buf, unsigned int size, const char *format,...)
Build a taskprocessor name with a sequence number on the end.
int ast_taskprocessor_alert_set_levels(struct ast_taskprocessor *tps, long low_water, long high_water)
Set the high and low alert water marks of the given taskprocessor queue.
#define AST_TASKPROCESSOR_MAX_NAME
Suggested maximum taskprocessor name length (less null terminator).
Definition: taskprocessor.h:61
int done
Definition: test_amihooks.c:48
const char * args
static struct test_options options
static struct test_val a
void ast_threadpool_shutdown(struct ast_threadpool *pool)
Shut down a threadpool and destroy it.
Definition: threadpool.c:966
struct ast_threadpool * ast_threadpool_create(const char *name, struct ast_threadpool_listener *listener, const struct ast_threadpool_options *options)
Create a new threadpool.
Definition: threadpool.c:916
#define AST_THREADPOOL_OPTIONS_VERSION
Definition: threadpool.h:73
struct ast_taskprocessor * ast_threadpool_serializer(const char *name, struct ast_threadpool *pool)
Serialized execution of tasks within a ast_threadpool.
Definition: threadpool.c:1331
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:978
#define ast_assert(a)
Definition: utils.h:776
#define ARRAY_LEN(a)
Definition: utils.h:703
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
Vector container support.
#define AST_VECTOR_REMOVE_ORDERED(vec, idx)
Remove an element from a vector by index while maintaining order.
Definition: vector.h:459
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
Definition: vector.h:349
#define AST_VECTOR_RW_WRLOCK(vec)
Obtain write lock on vector.
Definition: vector.h:898
#define AST_VECTOR_REMOVE_CMP_ORDERED(vec, value, cmp, cleanup)
Remove an element from a vector that matches the given comparison while maintaining order.
Definition: vector.h:551
#define AST_VECTOR_RW_UNLOCK(vec)
Unlock vector.
Definition: vector.h:908
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:742
#define AST_VECTOR_RW_FREE(vec)
Deallocates this locked vector.
Definition: vector.h:213
#define AST_VECTOR_CALLBACK(vec, callback, default_value,...)
Execute a callback on every element in a vector returning the first matched.
Definition: vector.h:776
#define AST_VECTOR_RW_RDLOCK(vec)
Obtain read lock on vector.
Definition: vector.h:888
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:873
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691
#define AST_VECTOR_RW_INIT(vec, size)
Initialize a vector with a read/write lock.
Definition: vector.h:169