Asterisk - The Open Source Telephony Project GIT-master-f36a736
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
46/* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
47#undef open
48#undef close
49
50/*! \brief Number of buckets for wizards (should be prime for performance reasons) */
51#define WIZARD_BUCKETS 7
52
53/*! \brief Number of buckets for types (should be prime for performance reasons) */
54#define TYPE_BUCKETS 53
55
56/*! \brief Number of buckets for instances (should be prime for performance reasons) */
57#define INSTANCE_BUCKETS 17
58
59/*! \brief Number of buckets for object fields (should be prime for performance reasons) */
60#define OBJECT_FIELD_BUCKETS 29
61
62#define NOTIFY_GENERIC_OBSERVERS(container, type, callback, ...) ({ \
63 struct ao2_iterator i = ao2_iterator_init(container, 0); \
64 struct type *observer; \
65 ao2_rdlock(container); \
66 while ((observer = ao2_iterator_next(&i))) { \
67 if (observer->callbacks->callback) { \
68 observer->callbacks->callback(__VA_ARGS__); \
69 } \
70 ao2_cleanup(observer); \
71 } \
72 ao2_unlock(container); \
73 ao2_iterator_cleanup(&i); \
74})
75
76#define NOTIFY_GLOBAL_OBSERVERS(container, callback, ...) \
77 NOTIFY_GENERIC_OBSERVERS(container, sorcery_global_observer, callback, __VA_ARGS__)
78
79#define NOTIFY_INSTANCE_OBSERVERS(container, callback, ...) \
80 NOTIFY_GENERIC_OBSERVERS(container, sorcery_instance_observer, callback, __VA_ARGS__)
81
82#define NOTIFY_WIZARD_OBSERVERS(container, callback, ...) \
83 NOTIFY_GENERIC_OBSERVERS(container, sorcery_wizard_observer, callback, __VA_ARGS__)
84
85/*! \brief Thread pool for observers */
87
88/*! \brief Structure for an internal wizard instance */
90 /*!
91 * \brief Wizard interface itself
92 * \warning Callbacks must always be declared first in this structure
93 * so an ao2_ref on &callbacks will adjust the ref count on
94 * internal_wizard.
95 */
97
98 /*! \brief Observers */
100};
101
102/*! \brief Structure for a wizard instance which operates on objects */
104 /*! \brief Wizard interface itself */
106
107 /*! \brief Unique data for the wizard */
108 void *data;
109
110 /*! \brief Wizard is acting as an object cache */
111 unsigned int caching:1;
112
113 /*! \brief Wizard is read_only */
114 unsigned int read_only:1;
115
116 /*! \brief Wizard allows others of the same type */
117 unsigned int allow_duplicates:1;
118
119 /*! \brief Wizard arguments */
120 char wizard_args[0];
121};
122
123/*! \brief Interface for a sorcery object type wizards */
124AST_VECTOR_RW(ast_sorcery_object_wizards, struct ast_sorcery_object_wizard *);
125
126/*! \brief Structure for internal sorcery object information */
128 /*! \brief Unique identifier of this object */
129 char *id;
130
131 /*! \brief Type of object */
133
134 /*! \brief Optional object destructor */
136
137 /*! \brief Extended object fields */
139
140 /*! \brief Time that the object was created */
141 struct timeval created;
142
143 /*! \brief Whether this object has dynamic contents or not */
144 unsigned int has_dynamic_contents:1;
145};
146
147/*! \brief Structure for registered object type */
149 /*! \brief Unique name of the object type */
151
152 /*! \brief Optional transformation callback */
154
155 /*! \brief Optional object set apply callback */
157
158 /*! \brief Optional object copy callback */
160
161 /*! \brief Optional object diff callback */
163
164 /*! \brief Wizard instances */
165 struct ast_sorcery_object_wizards wizards;
166
167 /*! \brief Object fields */
169
170 /*! \brief Configuration framework general information */
171 struct aco_info *info;
172
173 /*! \brief Configuration framework file information */
174 struct aco_file *file;
175
176 /*! \brief Type details */
178
179 /*! \brief Observers */
181
182 /*! \brief Serializer for observers */
184
185 /*! \brief Specifies if object type is reloadable or not */
186 unsigned int reloadable:1;
187};
188
189/*! \brief Structure for registered object type observer */
191 /*! \brief Pointer to the observer implementation */
193};
194
195/*! \brief Structure used for observer invocations */
197 /*! \brief Pointer to the object type */
199
200 /*! \brief Pointer to the object */
201 void *object;
202};
203
204/*! \brief Structure for registered object field */
206 /*! \brief Name of the field */
208
209 /*! \brief The compiled name regex if name is a regex */
210 regex_t *name_regex;
211
212 /*! \brief Callback function for translation of a single value */
214
215 /*! \brief Callback function for translation of multiple values */
217
218 /*! \brief Position of the field */
219 intptr_t args[];
220};
221
222/*! \brief Proxy object for sorcery */
225 /*! \brief The name of the module owning this sorcery instance */
226 char module_name[0];
227};
228
229/*! \brief Full structure for sorcery */
231 /*! \brief Container for known object types */
233
234 /*! \brief Observers */
236
237 /*! \brief Pointer to module_name in the associated sorcery_proxy. */
239};
240
241/*! \brief Structure for passing load/reload details */
243 /*! \brief Sorcery structure in use */
244 const struct ast_sorcery *sorcery;
245
246 /*! \brief Type of object being loaded */
247 const char *type;
248
249 /*! \brief Whether this is a reload or not */
250 unsigned int reload:1;
251
252 /*! \brief Whether this is forced or not */
253 unsigned int force:1;
254};
255
256/*! \brief Registered sorcery wizards */
257static struct ao2_container *wizards;
258
259/* The following 3 observer wrappers must name their
260 * external observer 'callbacks' and it must be
261 * the first member of the structure. Common macros
262 * and container callbacks depend on it.
263 */
264
265/*! \brief A global observer wrapper */
268};
269
270/*! \brief An instance observer wrapper */
273};
274
275/*! \brief A wizard observer wrapper */
278};
279
280/*! \brief Registered global observers */
282
283/*! \brief Registered sorcery instances */
285
286static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
287{
288 int *field = (int *)(obj + args[0]);
289 return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
290}
291
292static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
293{
294 unsigned int *field = (unsigned int *)(obj + args[0]);
295 return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
296}
297
298static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
299{
300 double *field = (double *)(obj + args[0]);
301 return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
302}
303
304static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
305{
306 ast_string_field *field = (const char **)(obj + args[0]);
307 return !(*buf = ast_strdup(*field)) ? -1 : 0;
308}
309
310static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
311{
312 unsigned int *field = (unsigned int *)(obj + args[0]);
313 return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
314}
315
316static int yesno_handler_fn(const void *obj, const intptr_t *args, char **buf)
317{
318 unsigned int *field = (unsigned int *)(obj + args[0]);
319 return !(*buf = ast_strdup(*field ? "yes" : "no")) ? -1 : 0;
320}
321
322static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
323{
324 struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
325 return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
326}
327
328static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
329{
330 char *field = (char *)(obj + args[0]);
331 return !(*buf = ast_strdup(field)) ? -1 : 0;
332}
333
334static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
335{
337 struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
338 return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
339}
340
342{
343 switch(type) {
344 case OPT_BOOL_T: return bool_handler_fn;
345 case OPT_YESNO_T: return yesno_handler_fn;
347 case OPT_CODEC_T: return codec_handler_fn;
348 case OPT_DOUBLE_T: return double_handler_fn;
349 case OPT_INT_T: return int_handler_fn;
352 case OPT_UINT_T: return uint_handler_fn;
353
354 default:
355 case OPT_CUSTOM_T: return NULL;
356 }
357
358 return NULL;
359}
360
361/*! \brief Hashing and comparison functions for sorcery wizards */
364
367
368/*! \brief Cleanup function for graceful shutdowns */
369static void sorcery_cleanup(void)
370{
374 wizards = NULL;
376 observers = NULL;
378 instances = NULL;
379}
380
381/*! \brief Compare function for sorcery instances */
383
384/*! \brief Hashing function for sorcery instances */
386
388{
391 .auto_increment = 1,
392 .max_size = 0,
393 .idle_timeout = 60,
394 .initial_size = 0,
395 };
397
399 if (!threadpool) {
400 return -1;
401 }
402
404 ast_sorcery_internal_wizard_hash_fn, NULL, ast_sorcery_internal_wizard_cmp_fn);
405 if (!wizards) {
406 return -1;
407 }
408
410 if (!observers) {
411 return -1;
412 }
413
415 sorcery_proxy_hash_fn, NULL, sorcery_proxy_cmp_fn);
416 if (!instances) {
417 return -1;
418 }
419
421
422 return 0;
423}
424
426{
427 struct ast_sorcery_internal_wizard *wizard = obj;
428
429 ao2_cleanup(wizard->observers);
430}
431
432int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
433{
434 struct ast_sorcery_internal_wizard *wizard;
435 int res = -1;
436
437 ast_assert(!ast_strlen_zero(interface->name));
438
440
441 if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
442 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
443 interface->name);
444 goto done;
445 }
446
447 if (!(wizard = ao2_alloc(sizeof(*wizard), sorcery_internal_wizard_destructor))) {
448 goto done;
449 }
450
451 wizard->callbacks = *interface;
452 wizard->callbacks.module = module;
453
455 if (!wizard->observers) {
456 goto done;
457 }
458
460 res = 0;
461
462 ast_verb(5, "Sorcery registered wizard '%s'\n", interface->name);
463
464 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_registered,
465 interface->name, interface);
466
467done:
468 ao2_cleanup(wizard);
470
471 return res;
472}
473
475{
476 struct ast_sorcery_internal_wizard *wizard =
477 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL;
478
479 if (wizard) {
480 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_unregistering, wizard->callbacks.name, &wizard->callbacks);
481 ao2_unlink(wizards, wizard);
482 ao2_ref(wizard, -1);
483 ast_verb(5, "Sorcery unregistered wizard '%s'\n", interface->name);
484 return 0;
485 } else {
486 return -1;
487 }
488}
489
490/*! \brief Internal callback function for removing a generic observer */
491static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
492{
493 const struct sorcery_global_observer *observer = obj;
494
495 return (observer->callbacks == arg) ? CMP_MATCH : 0;
496}
497
499{
500 struct sorcery_global_observer *cb;
501
502 cb = ao2_alloc(sizeof(*cb), NULL);
503 if (!cb) {
504 return -1;
505 }
506
507 cb->callbacks = callbacks;
508 ao2_link(observers, cb);
509 ao2_ref(cb, -1);
510
511 return 0;
512}
513
516{
518}
519
522{
523 struct sorcery_instance_observer *cb;
524
525 cb = ao2_alloc(sizeof(*cb), NULL);
526 if (!cb) {
527 return -1;
528 }
529
530 cb->callbacks = callbacks;
532 ao2_ref(cb, -1);
533
534 return 0;
535}
536
539{
541}
542
545{
546 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
547 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
549
550 if (wizard) {
551 struct sorcery_wizard_observer *cb;
552
553 cb = ao2_alloc(sizeof(*cb), NULL);
554 if (!cb) {
555 return -1;
556 }
557
558 cb->callbacks = callbacks;
559 ao2_link(wizard->observers, cb);
560 ao2_ref(cb, -1);
561
562 return 0;
563 }
564
565 return -1;
566}
567
570{
571 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
572 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
574
575 if (wizard) {
577 }
578}
579
580/*! \brief Destructor called when sorcery structure is destroyed */
581static void sorcery_destructor(void *obj)
582{
583 struct ast_sorcery *sorcery = obj;
584
585 if (sorcery->observers) {
587 }
590}
591
592/*! \brief Hashing function for sorcery types */
595
596static void sorcery_proxy_cb(void *weakproxy, void *data)
597{
598 ao2_unlink(instances, weakproxy);
599}
600
601struct ast_sorcery *__ast_sorcery_open(const char *module_name, const char *file, int line, const char *func)
602{
603 struct sorcery_proxy *proxy;
604 struct ast_sorcery *sorcery;
605
607
610 __PRETTY_FUNCTION__, file, line, func);
611 if (sorcery) {
613
614 return sorcery;
615 }
616
617 proxy = ao2_t_weakproxy_alloc(sizeof(*proxy) + strlen(module_name) + 1, NULL, module_name);
618 if (!proxy) {
619 goto failure_cleanup;
620 }
621 strcpy(proxy->module_name, module_name); /* Safe */
622
624 if (!sorcery) {
625 goto failure_cleanup;
626 }
627
629
630 /* We have exclusive access to proxy and sorcery, no need for locking here. */
631 if (ao2_t_weakproxy_set_object(proxy, sorcery, OBJ_NOLOCK, "weakproxy link")) {
632 goto failure_cleanup;
633 }
634
636 goto failure_cleanup;
637 }
638
640 ast_sorcery_object_type_hash_fn, NULL, ast_sorcery_object_type_cmp_fn);
641 if (!sorcery->types) {
642 goto failure_cleanup;
643 }
644
646 goto failure_cleanup;
647 }
648
650 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
651 goto failure_cleanup;
652 }
653
655 ao2_ref(proxy, -1);
656
658
660 return sorcery;
661
662failure_cleanup:
663 /* cleanup of sorcery may result in locking instances, so make sure we unlock first. */
666 ao2_cleanup(proxy);
667
668 return NULL;
669}
670
671/*! \brief Search function for sorcery instances */
673{
675}
676
677/*! \brief Destructor function for object types */
678static void sorcery_object_type_destructor(void *obj)
679{
680 struct ast_sorcery_object_type *object_type = obj;
681
682 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
684 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
685 AST_VECTOR_RW_FREE(&object_type->wizards);
686 ao2_cleanup(object_type->fields);
687 ao2_cleanup(object_type->observers);
688
689 if (object_type->info) {
690 aco_info_destroy(object_type->info);
691 ast_free(object_type->info);
692 }
693
694 ast_free(object_type->file);
695
697}
698
699/*! \brief Internal function which allocates an object type structure */
700static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
701{
702#define INITIAL_WIZARD_VECTOR_SIZE 5
703 struct ast_sorcery_object_type *object_type;
704 char tps_name[AST_TASKPROCESSOR_MAX_NAME + 1];
705
706 if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
707 return NULL;
708 }
709
710 /* Order matters for object wizards */
711 if (AST_VECTOR_RW_INIT(&object_type->wizards, INITIAL_WIZARD_VECTOR_SIZE) != 0) {
712 ao2_ref(object_type, -1);
713 return NULL;
714 }
715
717 OBJECT_FIELD_BUCKETS, ast_sorcery_object_field_hash_fn, NULL, ast_sorcery_object_field_cmp_fn);
718 if (!object_type->fields) {
719 ao2_ref(object_type, -1);
720 return NULL;
721 }
722
724 NULL, NULL);
725 if (!object_type->observers) {
726 ao2_ref(object_type, -1);
727 return NULL;
728 }
729
730 object_type->info = ast_calloc(1,
731 sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0]));
732 if (!object_type->info) {
733 ao2_ref(object_type, -1);
734 return NULL;
735 }
736
737 object_type->file = ast_calloc(1,
738 sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0]));
739 if (!object_type->file) {
740 ao2_ref(object_type, -1);
741 return NULL;
742 }
743
744 /* Create name with seq number appended. */
745 ast_taskprocessor_build_name(tps_name, sizeof(tps_name), "sorcery/%s", type);
746
747 if (!(object_type->serializer = ast_threadpool_serializer(tps_name, threadpool))) {
748 ao2_ref(object_type, -1);
749 return NULL;
750 }
751
752 object_type->info->files[0] = object_type->file;
753 object_type->info->files[1] = NULL;
754 object_type->info->module = module;
755
756 ast_copy_string(object_type->name, type, sizeof(object_type->name));
757
758 return object_type;
759}
760
761/*! \brief Object wizard destructor */
763{
764 struct ast_sorcery_object_wizard *object_wizard = obj;
765
766 if (object_wizard->data && object_wizard->wizard->callbacks.close) {
767 object_wizard->wizard->callbacks.close(object_wizard->data);
768 }
769
770 if (object_wizard->wizard) {
771 ast_module_unref(object_wizard->wizard->callbacks.module);
772 }
773
774 ao2_cleanup(object_wizard->wizard);
775}
776
777/*! \brief Return the number of wizards mapped to an object type */
779 const char *type)
780{
782
783 if (!object_type) {
784 return -1;
785 }
786
787 return AST_VECTOR_SIZE(&object_type->wizards);
788}
789
791 const char *type, int index, struct ast_sorcery_wizard **wizard, void **data)
792{
794 struct ast_sorcery_object_wizard *owizard;
795
796 if (!object_type) {
797 return -1;
798 }
799
800 if (index < 0 || index >= AST_VECTOR_SIZE(&object_type->wizards)) {
801 return -1;
802 }
803
804 owizard = AST_VECTOR_GET(&object_type->wizards, index);
805
806 if (wizard != NULL) {
807 *wizard = &(owizard->wizard->callbacks);
808 ao2_bump(owizard->wizard);
809 } else {
810 return -1;
811 }
812
813 if (data != NULL) {
814 *data = owizard->data;
815 }
816
817 return 0;
818}
819
821 const char *object_type_name, const char *module, const char *wizard_type_name,
822 const char *wizard_args)
823{
824 RAII_VAR(struct ast_sorcery_object_type *, object_type,
825 ao2_find(sorcery->types, object_type_name, OBJ_SEARCH_KEY), ao2_cleanup);
826 int res = -1;
827 int i;
828
829 if (!object_type) {
830 return res;
831 }
832
833 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
834 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
835 struct ast_sorcery_object_wizard *wizard = AST_VECTOR_GET(&object_type->wizards, i);
836
837 if (strcmp(wizard->wizard->callbacks.name, wizard_type_name) == 0
838 && strcmp(S_OR(wizard->wizard_args, ""), S_OR(wizard_args, "")) == 0) {
839 ao2_cleanup(AST_VECTOR_REMOVE_ORDERED(&object_type->wizards, i));
840 res = 0;
841 break;
842 }
843 }
844 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
845
846 return res;
847}
848
849/*! \brief Internal function removes a wizard mapping */
851 const char *type, const char *module, const char *name)
852{
854 int res;
855
856 if (!object_type) {
857 return -1;
858 }
859
860 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
861#define WIZARD_NAME_COMPARE(a, b) (strcmp((a)->wizard->callbacks.name, (b)) == 0)
863#undef WIZARD_NAME_COMPARE
864 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
865
866 return res;
867}
868
870 const char *object_type_name, const char *module, const char *wizard_type_name,
871 const char *wizard_args, enum ast_sorcery_wizard_apply_flags flags, int position,
872 struct ast_sorcery_wizard **wizard, void **wizard_data)
873{
874 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, object_type_name, OBJ_KEY), ao2_cleanup);
875 RAII_VAR(struct ast_sorcery_internal_wizard *, internal_wizard, ao2_find(wizards, wizard_type_name, OBJ_KEY), ao2_cleanup);
876 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
877 int created = 0;
878
879 object_wizard = ao2_alloc(sizeof(*object_wizard)
880 + (ast_strlen_zero(wizard_args) ? 0 : strlen(wizard_args) + 1),
882
883 if (!object_wizard) {
885 }
886
887 if (!internal_wizard
888 || internal_wizard->callbacks.module != ast_module_running_ref(internal_wizard->callbacks.module)) {
890 "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
891 wizard_type_name, object_type_name);
893 }
894
895 if (!object_type) {
896 if (!(object_type = sorcery_object_type_alloc(object_type_name, module))) {
897 ast_module_unref(internal_wizard->callbacks.module);
899 }
900 created = 1;
901 }
902
903 AST_VECTOR_RW_WRLOCK(&object_type->wizards);
904 if (!created) {
905 struct ast_sorcery_object_wizard *found;
906
907#define WIZARD_COMPARE(a, b) ((a)->wizard == (b))
908 found = AST_VECTOR_GET_CMP(&object_type->wizards, internal_wizard, WIZARD_COMPARE);
909#undef WIZARD_COMPARE
910 if (found
912 ast_debug(1, "Wizard %s already applied to object type %s\n",
913 internal_wizard->callbacks.name, object_type->name);
914 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
915 ast_module_unref(internal_wizard->callbacks.module);
917 }
918 }
919
920 ast_debug(5, "Calling wizard %s open callback on object type %s\n",
921 wizard_type_name, object_type->name);
922 if (internal_wizard->callbacks.open && !(object_wizard->data = internal_wizard->callbacks.open(wizard_args))) {
923 ast_log(LOG_WARNING, "Wizard '%s' failed to open mapping for object type '%s' with data: %s\n",
924 wizard_type_name, object_type->name, S_OR(wizard_args, ""));
925 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
926 ast_module_unref(internal_wizard->callbacks.module);
928 }
929
930 object_wizard->wizard = ao2_bump(internal_wizard);
931 object_wizard->caching = !!(flags & AST_SORCERY_WIZARD_APPLY_CACHING);
932 object_wizard->read_only = !!(flags & AST_SORCERY_WIZARD_APPLY_READONLY);
933 if (wizard_args) {
934 strcpy(object_wizard->wizard_args, wizard_args); /* Safe */
935 }
936
937 if (position == AST_SORCERY_WIZARD_POSITION_LAST) {
938 position = AST_VECTOR_SIZE(&object_type->wizards);
939 }
940
941 if (AST_VECTOR_INSERT_AT(&object_type->wizards, position, object_wizard) != 0) {
942 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
944 }
945 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
946 ao2_bump(object_wizard);
947
948 if (created) {
949 ao2_link(sorcery->types, object_type);
950 }
951
953 sorcery->module_name, sorcery, object_type_name, &internal_wizard->callbacks, wizard_args,
954 object_wizard->data);
955
956 if (wizard) {
957 *wizard = &internal_wizard->callbacks;
958 }
959 if (wizard_data) {
960 *wizard_data = object_wizard->data;
961 }
962
964}
965
966/*! \brief Internal function which creates an object type and inserts a wizard mapping */
968 const char *type, const char *module, const char *name,
969 const char *data, unsigned int caching, int position)
970{
973 position, NULL, NULL);
974}
975
976/*! \brief Internal function which creates an object type and adds a wizard mapping */
978 const char *type, const char *module, const char *name,
979 const char *data, unsigned int caching)
980{
983}
984
985enum ast_sorcery_apply_result __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
986{
987 struct ast_flags flags = { 0 };
988 struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
989 struct ast_variable *mapping;
991
992 if (!config) {
994 }
995
998 }
999
1000 for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
1001 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
1002 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
1003 char *options = mapping_name;
1004 char *type = strsep(&options, "/");
1005 char *data = mapping_value;
1006 char *wizard = strsep(&data, ",");
1007 unsigned int caching = 0;
1008
1009 /* If no object type or wizard exists just skip, nothing we can do */
1010 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
1011 continue;
1012 }
1013
1014 /* If the wizard is configured as a cache treat it as such */
1015 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
1016 caching = 1;
1017 }
1018
1019 /* Any error immediately causes us to stop */
1020 if (__ast_sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
1022 break;
1023 }
1024 }
1025
1027
1028 return res;
1029}
1030
1031enum ast_sorcery_apply_result __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
1032{
1034
1035 /* Defaults can not be added if any existing mapping exists */
1036 if (object_type) {
1038 }
1039
1040 return __ast_sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
1041}
1042
1043static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1044{
1045 return ast_sorcery_object_set_extended(obj, var->name, var->value);
1046}
1047
1048static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
1049{
1050 const struct ast_sorcery_object_details *details = obj;
1051
1052 if (details->object->extended) {
1053 *fields = ast_variables_dup(details->object->extended);
1054 } else {
1055 *fields = NULL;
1056 }
1057
1058 return 0;
1059}
1060
1062{
1063 struct ast_sorcery_object_type *object_type;
1064 int res = -1;
1065
1067 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY | OBJ_NOLOCK);
1068 if (object_type && object_type->type.type == ACO_ITEM) {
1069 ao2_unlink_flags(sorcery->types, object_type, OBJ_NOLOCK);
1070 res = 0;
1071 }
1073
1074 /* XXX may need to add an instance unregister observer callback on success. */
1075
1076 ao2_cleanup(object_type);
1077 return res;
1078}
1079
1081{
1083
1084 if (!object_type || object_type->type.item_alloc) {
1085 return -1;
1086 }
1087
1088 object_type->type.name = object_type->name;
1089 object_type->type.type = ACO_ITEM;
1090 object_type->type.category = ".?";
1091 object_type->type.item_alloc = alloc;
1092 object_type->type.hidden = hidden;
1093
1094 object_type->reloadable = reloadable;
1095 object_type->transform = transform;
1096 object_type->apply = apply;
1097 object_type->file->types[0] = &object_type->type;
1098 object_type->file->types[1] = NULL;
1099
1100 if (aco_info_init(object_type->info)) {
1101 return -1;
1102 }
1103
1105 return -1;
1106 }
1107
1108 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, object_type_registered,
1110
1111 return 0;
1112}
1113
1114int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water)
1115{
1116 struct ast_sorcery_object_type *object_type;
1117 int res = -1;
1118
1119 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1120 if (object_type) {
1122 low_water, high_water);
1123 ao2_ref(object_type, -1);
1124 }
1125 return res;
1126}
1127
1129{
1131
1132 if (!object_type) {
1133 return;
1134 }
1135
1136 object_type->copy = copy;
1137}
1138
1140{
1142
1143 if (!object_type) {
1144 return;
1145 }
1146
1147 object_type->diff = diff;
1148}
1149
1151{
1152 struct ast_sorcery_object_field *object_field = obj;
1153
1154 if (object_field->name_regex) {
1155 regfree(object_field->name_regex);
1156 ast_free(object_field->name_regex);
1157 }
1158}
1159
1160int 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)
1161{
1162#define MAX_REGEX_ERROR_LEN 128
1164 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1165 int rc;
1166
1167 if (!object_type || !object_type->type.item_alloc || !config_handler
1168 || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
1169 return -1;
1170 }
1171
1172 ast_copy_string(object_field->name, regex, sizeof(object_field->name));
1173 object_field->multiple_handler = sorcery_handler;
1174
1175 if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
1176 return -1;
1177 }
1178
1179 if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
1180 char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
1181 regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
1182 ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
1183 return -1;
1184 }
1185
1186 ao2_link(object_type->fields, object_field);
1187 __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
1188
1189 return 0;
1190}
1191
1192int __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,
1193 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, ...)
1194{
1196 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1197 int pos;
1198 va_list args;
1199
1200 if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
1201 return -1;
1202 }
1203
1204 if (!sorcery_handler) {
1205 sorcery_handler = sorcery_field_default_handler(opt_type);
1206 }
1207
1208 if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
1209 return -1;
1210 }
1211
1212 ast_copy_string(object_field->name, name, sizeof(object_field->name));
1213 object_field->handler = sorcery_handler;
1214 object_field->multiple_handler = multiple_handler;
1215
1216 va_start(args, argc);
1217 for (pos = 0; pos < argc; pos++) {
1218 object_field->args[pos] = va_arg(args, size_t);
1219 }
1220 va_end(args);
1221
1222 if (!alias) {
1223 ao2_link(object_type->fields, object_field);
1224 }
1225
1226 /* TODO: Improve this hack */
1227 if (!argc) {
1228 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
1229 } else if (argc == 1) {
1230 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1231 object_field->args[0]);
1232 } else if (argc == 2) {
1233 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1234 object_field->args[0], object_field->args[1]);
1235 } else if (argc == 3) {
1236 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1237 object_field->args[0], object_field->args[1], object_field->args[2]);
1238 } else {
1239 ast_assert(0); /* The hack... she does us no good for this */
1240 }
1241
1242 return 0;
1243}
1244
1245/*! \brief Retrieves whether or not the type is reloadable */
1246static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
1247{
1248 RAII_VAR(struct ast_sorcery_object_type *, object_type,
1250 return object_type && object_type->reloadable;
1251}
1252
1253static int sorcery_wizard_load(void *obj, void *arg, int flags)
1254{
1255 struct ast_sorcery_object_wizard *wizard = obj;
1256 struct sorcery_load_details *details = arg;
1257 void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
1258
1259 if (details->reload) {
1260 if (details->force && wizard->wizard->callbacks.force_reload) {
1261 load = wizard->wizard->callbacks.force_reload;
1262 } else {
1263 load = wizard->wizard->callbacks.reload;
1264 }
1265 } else {
1266 load = wizard->wizard->callbacks.load;
1267 }
1268
1269 if (load) {
1270 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
1271 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1272
1273 load(wizard->data, details->sorcery, details->type);
1274
1275 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loaded,
1276 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1277 }
1278
1279 return 0;
1280}
1281
1282/*! \brief Destructor for observer invocation */
1284{
1285 struct sorcery_observer_invocation *invocation = obj;
1286
1287 ao2_cleanup(invocation->object_type);
1288 ao2_cleanup(invocation->object);
1289}
1290
1291/*! \brief Allocator function for observer invocation */
1293{
1294 struct sorcery_observer_invocation *invocation;
1295
1296 invocation = ao2_alloc_options(sizeof(*invocation),
1298 if (!invocation) {
1299 return NULL;
1300 }
1301
1302 ao2_ref(object_type, +1);
1303 invocation->object_type = object_type;
1304
1305 if (object) {
1306 ao2_ref(object, +1);
1307 invocation->object = object;
1308 }
1309
1310 return invocation;
1311}
1312
1313/*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1314static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1315{
1316 const struct ast_sorcery_object_type_observer *observer = obj;
1317
1318 if (observer->callbacks->loaded) {
1319 observer->callbacks->loaded(arg);
1320 }
1321
1322 return 0;
1323}
1324
1325/*! \brief Internal callback function which notifies observers that an object type has been loaded */
1327{
1328 struct sorcery_observer_invocation *invocation = data;
1329
1331 ao2_cleanup(invocation);
1332
1333 return 0;
1334}
1335
1336static int sorcery_object_load(void *obj, void *arg, int flags)
1337{
1338 struct ast_sorcery_object_type *type = obj;
1339 struct sorcery_load_details *details = arg;
1340
1341 if (!type->type.item_alloc) {
1342 return 0;
1343 }
1344
1345 details->type = type->name;
1346
1347 if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
1348 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
1349 details->type);
1350 return 0;
1351 }
1352
1353 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
1354 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1355
1356 AST_VECTOR_RW_RDLOCK(&type->wizards);
1357 AST_VECTOR_CALLBACK(&type->wizards, sorcery_wizard_load, NULL, details, 0);
1358 AST_VECTOR_RW_UNLOCK(&type->wizards);
1359
1360 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
1361 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1362
1363 if (ao2_container_count(type->observers)) {
1364 struct sorcery_observer_invocation *invocation;
1365
1367 if (invocation
1369 invocation)) {
1370 ao2_cleanup(invocation);
1371 }
1372 }
1373
1374 return 0;
1375}
1376
1378{
1379 struct sorcery_load_details details = {
1380 .sorcery = sorcery,
1381 .reload = 0,
1382 };
1383
1384 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1386
1388
1391}
1392
1393void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1394{
1396 struct sorcery_load_details details = {
1397 .sorcery = sorcery,
1398 .reload = 0,
1399 };
1400
1401 if (!object_type) {
1402 return;
1403 }
1404
1405 sorcery_object_load(object_type, &details, 0);
1406}
1407
1409{
1410 struct sorcery_load_details details = {
1411 .sorcery = sorcery,
1412 .reload = 1,
1413 };
1414
1415 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1417
1419
1422
1423}
1424
1426{
1427 struct sorcery_load_details details = {
1428 .sorcery = sorcery,
1429 .reload = 1,
1430 .force = 1,
1431 };
1432
1433 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1435
1437
1440}
1441
1442void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1443{
1445 struct sorcery_load_details details = {
1446 .sorcery = sorcery,
1447 .reload = 1,
1448 };
1449
1450 if (!object_type) {
1451 return;
1452 }
1453
1454 sorcery_object_load(object_type, &details, 0);
1455}
1456
1458{
1460 struct sorcery_load_details details = {
1461 .sorcery = sorcery,
1462 .reload = 1,
1463 .force = 1,
1464 };
1465
1466 if (!object_type) {
1467 return;
1468 }
1469
1470 sorcery_object_load(object_type, &details, 0);
1471}
1472
1474{
1475 ao2_ref(sorcery, +1);
1476}
1477
1478static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1479{
1480 struct ast_variable *tmp = NULL;
1481 char *buf = NULL;
1482
1483 if (!object_field->handler) {
1484 return NULL;
1485 }
1486
1487 if (!(object_field->handler(object, object_field->args, &buf))) {
1488 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1489 }
1490 ast_free(buf);
1491
1492 return tmp;
1493}
1494
1495static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1496{
1497 struct ast_variable *tmp = NULL;
1498
1499 if (!object_field->multiple_handler) {
1500 return NULL;
1501 }
1502
1503 if (object_field->multiple_handler(object, &tmp)) {
1505 tmp = NULL;
1506 }
1507
1508 return tmp;
1509}
1510
1512 const void *object, enum ast_sorcery_field_handler_flags flags)
1513{
1514 const struct ast_sorcery_object_details *details = object;
1515 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1516 struct ao2_iterator i;
1517 struct ast_sorcery_object_field *object_field;
1518 struct ast_variable *head = NULL;
1519 struct ast_variable *tail = NULL;
1520
1521 if (!object_type) {
1522 return NULL;
1523 }
1524
1525 i = ao2_iterator_init(object_type->fields, 0);
1526
1527 for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1528 struct ast_variable *tmp;
1529
1530 switch (flags) {
1532 if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1533 (tmp = get_single_field_as_var_list(object, object_field))) {
1534 break;
1535 }
1536 continue;
1538 if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1539 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1540 break;
1541 }
1542 continue;
1544 if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1545 break;
1546 }
1547 continue;
1549 if ((tmp = get_single_field_as_var_list(object, object_field))) {
1550 break;
1551 }
1552 continue;
1553 default:
1554 continue;
1555 }
1556
1557 tail = ast_variable_list_append_hint(&head, tail, tmp);
1558 }
1559
1561
1562 return head;
1563}
1564
1565struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1566{
1567 const struct ast_sorcery_object_details *details = object;
1568 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1569 struct ao2_iterator i;
1570 struct ast_sorcery_object_field *object_field;
1571 struct ast_json *json = ast_json_object_create();
1572 int res = 0;
1573
1574 if (!object_type || !json) {
1575 ast_json_unref(json);
1576 return NULL;
1577 }
1578
1579 i = ao2_iterator_init(object_type->fields, 0);
1580
1581 for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1582 if (object_field->multiple_handler) {
1583 struct ast_variable *tmp = NULL;
1584 struct ast_variable *field;
1585
1586 if ((res = object_field->multiple_handler(object, &tmp))) {
1588 ao2_ref(object_field, -1);
1589 break;
1590 }
1591
1592 for (field = tmp; field; field = field->next) {
1593 struct ast_json *value = ast_json_string_create(field->value);
1594
1595 if (!value || ast_json_object_set(json, field->name, value)) {
1596 res = -1;
1597 break;
1598 }
1599 }
1600
1602 } else if (object_field->handler) {
1603 char *buf = NULL;
1604 struct ast_json *value = NULL;
1605
1606 if (object_field->handler(object, object_field->args, &buf)
1608 || ast_json_object_set(json, object_field->name, value)) {
1609 ast_free(buf);
1610 ast_debug(5, "Skipping field '%s' for object type '%s'\n",
1611 object_field->name, object_type->name);
1612 continue;
1613 }
1614
1615 ast_free(buf);
1616 } else {
1617 continue;
1618 }
1619 }
1620
1622
1623 /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1624 if (res) {
1625 ast_json_unref(json);
1626 json = NULL;
1627 }
1628
1629 return json;
1630}
1631
1632int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1633{
1634 const struct ast_sorcery_object_details *details = object;
1635 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1636 RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1637 struct ast_variable *field;
1638 int res = 0;
1639
1640 if (!object_type) {
1641 return -1;
1642 }
1643
1644 if (object_type->transform && (transformed = object_type->transform(objectset))) {
1645 field = transformed;
1646 } else {
1647 field = objectset;
1648 }
1649
1650 for (; field; field = field->next) {
1651 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1652 break;
1653 }
1654 }
1655
1656 if (!res && object_type->apply) {
1657 res = object_type->apply(sorcery, object);
1658 }
1659
1660 return res;
1661}
1662
1663int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1664{
1665 const struct ast_variable *field;
1666 int res = 0;
1667
1668 *changes = NULL;
1669
1670 /* Unless the ast_variable list changes when examined... it can't differ from itself */
1671 if (original == modified) {
1672 return 0;
1673 }
1674
1675 for (field = modified; field; field = field->next) {
1676 const char *old_value = ast_variable_find_in_list(original, field->name);
1677
1678 if (!old_value || strcmp(old_value, field->value)) {
1679 struct ast_variable *tmp;
1680
1681 if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1682 res = -1;
1683 break;
1684 }
1685
1686 tmp->next = *changes;
1687 *changes = tmp;
1688 }
1689 }
1690
1691 /* If an error occurred do not return a partial changeset */
1692 if (res) {
1693 ast_variables_destroy(*changes);
1694 *changes = NULL;
1695 }
1696
1697 return res;
1698}
1699
1700static void sorcery_object_destructor(void *object)
1701{
1702 struct ast_sorcery_object_details *details = object;
1703
1704 if (details->object->destructor) {
1705 details->object->destructor(object);
1706 }
1707
1709 ast_free(details->object->id);
1710}
1711
1712void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj)
1713{
1714 void *object = ao2_alloc_with_lockobj(size + sizeof(struct ast_sorcery_object),
1715 sorcery_object_destructor, lockobj, "");
1716 struct ast_sorcery_object_details *details = object;
1717
1718 if (!object) {
1719 return NULL;
1720 }
1721
1722 details->object = object + size;
1723 details->object->destructor = destructor;
1724
1725 return object;
1726}
1727
1728void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1729{
1730 void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object),
1732 struct ast_sorcery_object_details *details = object;
1733
1734 if (!object) {
1735 return NULL;
1736 }
1737
1738 details->object = object + size;
1739 details->object->destructor = destructor;
1740
1741 return object;
1742}
1743
1744void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1745{
1747 struct ast_sorcery_object_details *details;
1748
1749 if (!object_type || !object_type->type.item_alloc ||
1750 !(details = object_type->type.item_alloc(id))) {
1751 return NULL;
1752 }
1753
1754 if (ast_strlen_zero(id)) {
1755 char uuid[AST_UUID_STR_LEN];
1756
1758 details->object->id = ast_strdup(uuid);
1759 } else {
1760 details->object->id = ast_strdup(id);
1761 }
1762 if (!details->object->id) {
1763 ao2_ref(details, -1);
1764 return NULL;
1765 }
1766
1767 details->object->created = ast_tvnow();
1768 ast_copy_string(details->object->type, type, sizeof(details->object->type));
1769
1770 if (aco_set_defaults(&object_type->type, id, details)) {
1771 ao2_ref(details, -1);
1772 return NULL;
1773 }
1774
1775 return details;
1776}
1777
1778void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1779{
1780 const struct ast_sorcery_object_details *details = object;
1781 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1783 RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1784 int res = 0;
1785
1786 if (!copy) {
1787 return NULL;
1788 } else if (object_type->copy) {
1789 res = object_type->copy(object, copy);
1790 } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1791 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1792 } else {
1793 /* No native copy available and could not create an objectset, this copy has failed */
1794 res = -1;
1795 }
1796
1797 if (res) {
1799 copy = NULL;
1800 }
1801
1802 return copy;
1803}
1804
1805int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1806{
1808
1809 *changes = NULL;
1810
1811 if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1812 return -1;
1813 }
1814
1815 if (original == modified) {
1816 return 0;
1817 } else if (!object_type->diff) {
1818 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1819 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1820
1821 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1822 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1823
1824 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1825 } else {
1826 return object_type->diff(original, modified, changes);
1827 }
1828}
1829
1830/*! \brief Structure used when calling create, update, or delete */
1832 /*! \brief Pointer to the sorcery instance */
1833 const struct ast_sorcery *sorcery;
1834 /*! \brief Pointer to the object itself */
1835 void *obj;
1836};
1837
1838/*! \brief Internal function used to create an object in caching wizards */
1839static int sorcery_cache_create(void *obj, void *arg, int flags)
1840{
1841 const struct ast_sorcery_object_wizard *object_wizard = obj;
1842 const struct sorcery_details *details = arg;
1843
1844 if (!object_wizard->caching || !object_wizard->wizard->callbacks.create) {
1845 return 0;
1846 }
1847
1848 object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj);
1849
1850 return 0;
1851}
1852
1853void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1854{
1855 struct ast_sorcery_object_type *object_type;
1856 void *object = NULL;
1857 int i;
1858 unsigned int cached = 0;
1859
1860 if (ast_strlen_zero(id)) {
1861 return NULL;
1862 }
1863
1864 object_type = ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1865 if (!object_type) {
1866 return NULL;
1867 }
1868
1869 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
1870 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
1872 AST_VECTOR_GET(&object_type->wizards, i);
1873
1874 if (wizard->wizard->callbacks.retrieve_id &&
1875 !(object = wizard->wizard->callbacks.retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1876 continue;
1877 }
1878
1879 cached = wizard->caching;
1880 break;
1881 }
1882
1883 if (!cached && object) {
1884 struct sorcery_details sdetails = {
1885 .sorcery = sorcery,
1886 .obj = object,
1887 };
1888
1889 AST_VECTOR_CALLBACK(&object_type->wizards, sorcery_cache_create, NULL, &sdetails, 0);
1890 }
1891 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1892
1893 ao2_ref(object_type, -1);
1894 return object;
1895}
1896
1897void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1898{
1900 void *object = NULL;
1901 int i;
1902 unsigned int cached = 0;
1903
1904 if (!object_type) {
1905 return NULL;
1906 }
1907
1908 /* If returning multiple objects create a container to store them in */
1909 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1911 if (!object) {
1912 return NULL;
1913 }
1914 }
1915
1916 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
1917 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
1919 AST_VECTOR_GET(&object_type->wizards, i);
1920
1921 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1922 if (wizard->wizard->callbacks.retrieve_multiple) {
1923 wizard->wizard->callbacks.retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1924 }
1925 } else if (fields && wizard->wizard->callbacks.retrieve_fields) {
1926 if (wizard->wizard->callbacks.retrieve_fields) {
1927 object = wizard->wizard->callbacks.retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1928 }
1929 }
1930
1931 if (((flags & AST_RETRIEVE_FLAG_MULTIPLE) && (!ao2_container_count(object) || !wizard->caching)) || !object) {
1932 continue;
1933 }
1934
1935 cached = wizard->caching;
1936
1937 break;
1938 }
1939
1940 /* If we are returning a single object and it came from a non-cache source create it in any caches */
1941 if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1942 struct sorcery_details sdetails = {
1943 .sorcery = sorcery,
1944 .obj = object,
1945 };
1946
1947 AST_VECTOR_CALLBACK(&object_type->wizards, sorcery_cache_create, NULL, &sdetails, 0);
1948 }
1949 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1950
1951 return object;
1952}
1953
1954struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1955{
1957 struct ao2_container *objects;
1958 int i;
1959
1960 if (!object_type) {
1961 return NULL;
1962 }
1963
1965 if (!objects) {
1966 return NULL;
1967 }
1968
1969 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
1970 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
1972 AST_VECTOR_GET(&object_type->wizards, i);
1973
1974 if (!wizard->wizard->callbacks.retrieve_regex) {
1975 continue;
1976 }
1977
1978 wizard->wizard->callbacks.retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1979
1980 if (wizard->caching && ao2_container_count(objects)) {
1981 break;
1982 }
1983 }
1984 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
1985
1986 return objects;
1987}
1988
1989struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
1990{
1992 struct ao2_container *objects;
1993 int i;
1994
1995 if (!object_type) {
1996 return NULL;
1997 }
1998
2000 if (!objects) {
2001 return NULL;
2002 }
2003
2004 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2005 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2007 AST_VECTOR_GET(&object_type->wizards, i);
2008
2009 if (!wizard->wizard->callbacks.retrieve_prefix) {
2010 continue;
2011 }
2012
2013 wizard->wizard->callbacks.retrieve_prefix(sorcery, wizard->data, object_type->name, objects, prefix, prefix_len);
2014
2015 if (wizard->caching && ao2_container_count(objects)) {
2016 break;
2017 }
2018 }
2019 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2020
2021 return objects;
2022}
2023
2024/*! \brief Internal function which returns if the wizard has created the object */
2025static int sorcery_wizard_create(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2026{
2027 if (!object_wizard->wizard->callbacks.create || object_wizard->read_only) {
2028 ast_debug(5, "Sorcery wizard '%s' does not support creation\n", object_wizard->wizard->callbacks.name);
2029 return 0;
2030 }
2031
2032 if (object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) {
2033 return 0;
2034 }
2035
2036 return CMP_MATCH;
2037}
2038
2039/*! \brief Internal callback function which notifies an individual observer that an object has been created */
2040static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
2041{
2042 const struct ast_sorcery_object_type_observer *observer = obj;
2043
2044 if (observer->callbacks->created) {
2045 observer->callbacks->created(arg);
2046 }
2047
2048 return 0;
2049}
2050
2051/*! \brief Internal callback function which notifies observers that an object has been created */
2053{
2054 struct sorcery_observer_invocation *invocation = data;
2055
2057 ao2_cleanup(invocation);
2058
2059 return 0;
2060}
2061
2062int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
2063{
2064 const struct ast_sorcery_object_details *details = object;
2065 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2066 struct ast_sorcery_object_wizard *object_wizard = NULL;
2067 struct ast_sorcery_object_wizard *found_wizard;
2068 int i;
2069 struct sorcery_details sdetails = {
2070 .sorcery = sorcery,
2071 .obj = object,
2072 };
2073
2074 if (!object_type) {
2075 return -1;
2076 }
2077
2078 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2079 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2080 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2081 if (!found_wizard->caching
2082 && sorcery_wizard_create(found_wizard, &sdetails) == CMP_MATCH) {
2083 object_wizard = found_wizard;
2084 }
2085 }
2086
2087 if (object_wizard) {
2088 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2089 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2090 if (found_wizard->caching) {
2091 sorcery_wizard_create(found_wizard, &sdetails);
2092 }
2093 }
2094
2095 if (ao2_container_count(object_type->observers)) {
2096 struct sorcery_observer_invocation *invocation;
2097
2098 invocation = sorcery_observer_invocation_alloc(object_type, object);
2099 if (invocation
2101 invocation)) {
2102 ao2_cleanup(invocation);
2103 }
2104 }
2105 }
2106
2108
2109 return object_wizard ? 0 : -1;
2110}
2111
2112/*! \brief Internal callback function which notifies an individual observer that an object has been updated */
2113static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
2114{
2115 const struct ast_sorcery_object_type_observer *observer = obj;
2116
2117 if (observer->callbacks->updated) {
2118 observer->callbacks->updated(arg);
2119 }
2120
2121 return 0;
2122}
2123
2124/*! \brief Internal callback function which notifies observers that an object has been updated */
2126{
2127 struct sorcery_observer_invocation *invocation = data;
2128
2130 ao2_cleanup(invocation);
2131
2132 return 0;
2133}
2134
2135/*! \brief Internal function which returns if a wizard has updated the object */
2136static int sorcery_wizard_update(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2137{
2138 if (!object_wizard->wizard->callbacks.update || object_wizard->read_only) {
2139 ast_debug(5, "Sorcery wizard '%s' does not support updating\n", object_wizard->wizard->callbacks.name);
2140 return 0;
2141 }
2142
2143 if (object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj)) {
2144 return 0;
2145 }
2146
2147 return CMP_MATCH;
2148}
2149
2150int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
2151{
2152 const struct ast_sorcery_object_details *details = object;
2153 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2154 struct ast_sorcery_object_wizard *object_wizard = NULL;
2155 struct ast_sorcery_object_wizard *found_wizard;
2156 int i;
2157 struct sorcery_details sdetails = {
2158 .sorcery = sorcery,
2159 .obj = object,
2160 };
2161
2162 if (!object_type) {
2163 return -1;
2164 }
2165
2166 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2167 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2168 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2169 if (!found_wizard->caching
2170 && sorcery_wizard_update(found_wizard, &sdetails) == CMP_MATCH) {
2171 object_wizard = found_wizard;
2172 }
2173 }
2174
2175 if (object_wizard) {
2176 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2177 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2178 if (found_wizard->caching) {
2179 sorcery_wizard_update(found_wizard, &sdetails);
2180 }
2181 }
2182
2183 if (ao2_container_count(object_type->observers)) {
2184 struct sorcery_observer_invocation *invocation;
2185
2186 invocation = sorcery_observer_invocation_alloc(object_type, object);
2187 if (invocation
2189 invocation)) {
2190 ao2_cleanup(invocation);
2191 }
2192 }
2193 }
2194
2196
2197 return object_wizard ? 0 : -1;
2198}
2199
2200/*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
2201static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
2202{
2203 const struct ast_sorcery_object_type_observer *observer = obj;
2204
2205 if (observer->callbacks->deleted) {
2206 observer->callbacks->deleted(arg);
2207 }
2208
2209 return 0;
2210}
2211
2212/*! \brief Internal callback function which notifies observers that an object has been deleted */
2214{
2215 struct sorcery_observer_invocation *invocation = data;
2216
2218 ao2_cleanup(invocation);
2219
2220 return 0;
2221}
2222
2223/*! \brief Internal function which returns if a wizard has deleted the object */
2224static int sorcery_wizard_delete(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
2225{
2226 if (!object_wizard->wizard->callbacks.delete || object_wizard->read_only) {
2227 ast_debug(5, "Sorcery wizard '%s' does not support deletion\n", object_wizard->wizard->callbacks.name);
2228 return 0;
2229 }
2230
2231 if (object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj)) {
2232 return 0;
2233 }
2234
2235 return CMP_MATCH;
2236}
2237
2238int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
2239{
2240 const struct ast_sorcery_object_details *details = object;
2241 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2242 struct ast_sorcery_object_wizard *object_wizard = NULL;
2243 struct ast_sorcery_object_wizard *found_wizard;
2244 int i;
2245 struct sorcery_details sdetails = {
2246 .sorcery = sorcery,
2247 .obj = object,
2248 };
2249
2250 if (!object_type) {
2251 return -1;
2252 }
2253
2254 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2255 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2256 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2257 if (!found_wizard->caching
2258 && sorcery_wizard_delete(found_wizard, &sdetails) == CMP_MATCH) {
2259 object_wizard = found_wizard;
2260 }
2261 }
2262
2263 if (object_wizard) {
2264 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2265 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2266 if (found_wizard->caching) {
2267 sorcery_wizard_delete(found_wizard, &sdetails);
2268 }
2269 }
2270
2271 if (ao2_container_count(object_type->observers)) {
2272 struct sorcery_observer_invocation *invocation;
2273
2274 invocation = sorcery_observer_invocation_alloc(object_type, object);
2275 if (invocation
2277 invocation)) {
2278 ao2_cleanup(invocation);
2279 }
2280 }
2281 }
2282
2284
2285 return object_wizard ? 0 : -1;
2286}
2287
2288int ast_sorcery_is_stale(const struct ast_sorcery *sorcery, void *object)
2289{
2290 const struct ast_sorcery_object_details *details = object;
2291 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
2292 struct ast_sorcery_object_wizard *found_wizard;
2293 int res = 0;
2294 int i;
2295
2296 if (!object_type) {
2297 return -1;
2298 }
2299
2300 AST_VECTOR_RW_RDLOCK(&object_type->wizards);
2301 for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
2302 found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
2303
2304 if (found_wizard->wizard->callbacks.is_stale) {
2305 res |= found_wizard->wizard->callbacks.is_stale(sorcery, found_wizard->data, object);
2306 ast_debug(5, "After calling wizard '%s', object '%s' is %s\n",
2307 found_wizard->wizard->callbacks.name,
2309 res ? "stale" : "not stale");
2310 }
2311 }
2312 AST_VECTOR_RW_UNLOCK(&object_type->wizards);
2313
2314 return res;
2315}
2316
2317const char *ast_sorcery_object_get_id(const void *object)
2318{
2319 const struct ast_sorcery_object_details *details = object;
2320 return details->object->id;
2321}
2322
2323const struct timeval ast_sorcery_object_get_created(const void *object)
2324{
2325 const struct ast_sorcery_object_details *details = object;
2326 return details->object->created;
2327}
2328
2329const char *ast_sorcery_object_get_type(const void *object)
2330{
2331 const struct ast_sorcery_object_details *details = object;
2332 return details->object->type;
2333}
2334
2335const char *ast_sorcery_object_get_extended(const void *object, const char *name)
2336{
2337 const struct ast_sorcery_object_details *details = object;
2338 struct ast_variable *field;
2339
2340 for (field = details->object->extended; field; field = field->next) {
2341 if (!strcmp(field->name + 1, name)) {
2342 return field->value;
2343 }
2344 }
2345
2346 return NULL;
2347}
2348
2349int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
2350{
2352 struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
2353 const struct ast_sorcery_object_details *details = object;
2354
2355 if (!extended) {
2356 return -1;
2357 }
2358
2359 for (field = details->object->extended; field; previous = field, field = field->next) {
2360 if (!strcmp(field->name, name)) {
2361 if (previous) {
2362 previous->next = field->next;
2363 } else {
2364 details->object->extended = field->next;
2365 }
2366 field->next = NULL;
2367 break;
2368 }
2369 }
2370
2371 extended->next = details->object->extended;
2372 details->object->extended = extended;
2373
2374 return 0;
2375}
2376
2377unsigned int ast_sorcery_object_has_dynamic_contents(const void *object)
2378{
2379 const struct ast_sorcery_object_details *details = object;
2380
2381 return details->object->has_dynamic_contents;
2382}
2383
2385{
2386 const struct ast_sorcery_object_details *details = object;
2387
2388 details->object->has_dynamic_contents = 1;
2389}
2390
2392{
2395 int res;
2396
2397 if (!object_type || !callbacks) {
2398 return -1;
2399 }
2400
2401 if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
2402 return -1;
2403 }
2404
2405 observer->callbacks = callbacks;
2406 res = 0;
2407 if (!ao2_link(object_type->observers, observer)) {
2408 res = -1;
2409 }
2410 ao2_ref(observer, -1);
2411
2412 return res;
2413}
2414
2415/*! \brief Internal callback function for removing an observer */
2416static int sorcery_observer_remove(void *obj, void *arg, int flags)
2417{
2418 const struct ast_sorcery_object_type_observer *observer = obj;
2419
2420 return (observer->callbacks == arg) ? CMP_MATCH : 0;
2421}
2422
2424{
2425 RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
2426 struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
2427
2428 if (!sorcery) {
2429 return;
2430 }
2431 object_type = ao2_find(sorcery->types, type, OBJ_KEY);
2432 if (!object_type) {
2433 return;
2434 }
2435
2436 ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
2438}
2439
2440int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
2441{
2442 const void *object_left = obj;
2443 const void *object_right = arg;
2444 const char *right_key = arg;
2445 int cmp;
2446
2447 switch (flags & OBJ_SEARCH_MASK) {
2448 case OBJ_SEARCH_OBJECT:
2449 right_key = ast_sorcery_object_get_id(object_right);
2450 /* Fall through */
2451 case OBJ_SEARCH_KEY:
2452 cmp = strcmp(ast_sorcery_object_get_id(object_left), right_key);
2453 break;
2455 cmp = strncmp(ast_sorcery_object_get_id(object_left), right_key, strlen(right_key));
2456 break;
2457 default:
2458 cmp = 0;
2459 break;
2460 }
2461 return cmp;
2462}
2463
2464int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
2465{
2466 int cmp;
2467
2468 cmp = ast_sorcery_object_id_sort(obj, arg, flags);
2469 if (cmp) {
2470 return 0;
2471 }
2472 return CMP_MATCH;
2473}
2474
2475int ast_sorcery_object_id_hash(const void *obj, int flags)
2476{
2477 const char *key;
2478
2479 switch (flags & OBJ_SEARCH_MASK) {
2480 case OBJ_SEARCH_KEY:
2481 key = obj;
2482 break;
2483 case OBJ_SEARCH_OBJECT:
2484 key = ast_sorcery_object_get_id(obj);
2485 break;
2486 default:
2487 /* Hash can only work on something with a full key. */
2488 ast_assert(0);
2489 return 0;
2490 }
2491 return ast_str_hash(key);
2492}
2493
2495 const char *type)
2496{
2498}
2499
2500static int is_registered_cb(void *obj, void *arg, int flags)
2501{
2502 struct ast_sorcery_object_field *object_field = obj;
2503 char *name = arg;
2504 int rc = 0;
2505
2506 if (object_field->name_regex
2507 && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
2508 rc = CMP_MATCH;
2509 }
2510
2511 return rc;
2512}
2513
2515 const char *field_name)
2516{
2517 struct ast_sorcery_object_field *object_field;
2518 int res = 1;
2519
2520 ast_assert(object_type != NULL);
2521
2522 object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
2523
2524 if (!object_field) {
2525 object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
2526 }
2527
2528 if (!object_field) {
2529 res = 0;
2530 }
2531
2532 ao2_cleanup(object_field);
2533 return res;
2534}
2535
2537{
2538 return sorcery->module_name;
2539}
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
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
static int tmp()
Definition: bt_open.c:389
static const char type[]
Definition: chan_ooh323.c:109
static const char config[]
Definition: chan_ooh323.c:111
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
char * strsep(char **str, const char *delims)
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:3336
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:928
#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:544
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
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:647
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
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
struct ast_sorcery_instance_observer observer
static struct ast_sorcery * sorcery
struct @468 callbacks
#define NULL
Definition: resample.c:96
#define INSTANCE_BUCKETS
Number of buckets for instances (should be prime for performance reasons)
Definition: sorcery.c:57
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:2335
static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:286
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
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:2201
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
Unregister a sorcery wizard.
Definition: sorcery.c:474
static int sorcery_observers_notify_create(void *data)
Internal callback function which notifies observers that an object has been created.
Definition: sorcery.c:2052
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:2423
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:1160
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:2349
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:537
#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:1031
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:2113
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
Definition: sorcery.c:1377
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:568
static int sorcery_cache_create(void *obj, void *arg, int flags)
Internal function used to create an object in caching wizards.
Definition: sorcery.c:1839
const char * ast_sorcery_get_module(const struct ast_sorcery *sorcery)
Get the module that has opened the provided sorcery instance.
Definition: sorcery.c:2536
static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:328
const char * ast_sorcery_object_get_type(const void *object)
Get the type of a sorcery object.
Definition: sorcery.c:2329
static int sorcery_observers_notify_delete(void *data)
Internal callback function which notifies observers that an object has been deleted.
Definition: sorcery.c:2213
#define NOTIFY_GLOBAL_OBSERVERS(container, callback,...)
Definition: sorcery.c:76
static void sorcery_destructor(void *obj)
Destructor called when sorcery structure is destroyed.
Definition: sorcery.c:581
#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:1128
void ast_sorcery_object_set_has_dynamic_contents(const void *object)
Set the dynamic contents flag on a sorcery object.
Definition: sorcery.c:2384
static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:304
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
Create and potentially persist an object using an available wizard.
Definition: sorcery.c:2062
static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:334
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:2494
#define WIZARD_BUCKETS
Number of buckets for wizards (should be prime for performance reasons)
Definition: sorcery.c:51
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:1805
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:1853
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:1408
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:778
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:1954
int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
Register a sorcery wizard.
Definition: sorcery.c:432
static void sorcery_object_type_destructor(void *obj)
Destructor function for object types.
Definition: sorcery.c:678
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:2391
static int sorcery_observer_remove(void *obj, void *arg, int flags)
Internal callback function for removing an observer.
Definition: sorcery.c:2416
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:967
static struct ast_threadpool * threadpool
Thread pool for observers.
Definition: sorcery.c:86
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:1425
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:1393
static struct ast_variable * get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
Definition: sorcery.c:1478
#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:1495
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
Definition: sorcery.c:1728
static int sorcery_wizard_load(void *obj, void *arg, int flags)
Definition: sorcery.c:1253
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type)
Unregister an object type.
Definition: sorcery.c:1061
static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
Internal callback function for removing a generic observer.
Definition: sorcery.c:491
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:850
static void sorcery_proxy_cb(void *weakproxy, void *data)
Hashing function for sorcery types.
Definition: sorcery.c:596
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:1314
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2464
static int yesno_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:316
static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:310
static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
Definition: sorcery.c:1048
unsigned int ast_sorcery_object_has_dynamic_contents(const void *object)
Get whether an object contains dynamic contents or not.
Definition: sorcery.c:2377
void ast_sorcery_ref(struct ast_sorcery *sorcery)
Increase the reference count of a sorcery structure.
Definition: sorcery.c:1473
static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:292
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:1192
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:543
static void sorcery_object_destructor(void *object)
Definition: sorcery.c:1700
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:1080
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:2025
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:1663
#define NOTIFY_INSTANCE_OBSERVERS(container, callback,...)
Definition: sorcery.c:79
static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
Retrieves whether or not the type is reloadable.
Definition: sorcery.c:1246
static int sorcery_object_load(void *obj, void *arg, int flags)
Definition: sorcery.c:1336
static struct ao2_container * wizards
Registered sorcery wizards.
Definition: sorcery.c:257
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:985
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:2514
static struct ao2_container * instances
Registered sorcery instances.
Definition: sorcery.c:284
static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:322
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
ao2 object sorter based on sorcery id.
Definition: sorcery.c:2440
const struct timeval ast_sorcery_object_get_created(const void *object)
Get when the sorcery object was created.
Definition: sorcery.c:2323
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:1712
#define OBJECT_FIELD_BUCKETS
Number of buckets for object fields (should be prime for performance reasons)
Definition: sorcery.c:60
struct ao2_container * observers
Registered global observers.
Definition: sorcery.c:281
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:2040
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
Update an object.
Definition: sorcery.c:2150
static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
Definition: sorcery.c:1043
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:1632
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:790
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:2136
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:1457
static void sorcery_observer_invocation_destroy(void *obj)
Destructor for observer invocation.
Definition: sorcery.c:1283
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:1292
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:977
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:820
static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
Definition: sorcery.c:341
void ast_sorcery_global_observer_remove(const struct ast_sorcery_global_observer *callbacks)
Remove a global observer from sorcery.
Definition: sorcery.c:514
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:2224
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:1565
static void sorcery_cleanup(void)
Hashing and comparison functions for sorcery wizards.
Definition: sorcery.c:369
int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
Add a global observer to sorcery.
Definition: sorcery.c:498
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:1442
static int sorcery_observers_notify_update(void *data)
Internal callback function which notifies observers that an object has been updated.
Definition: sorcery.c:2125
#define NOTIFY_WIZARD_OBSERVERS(container, callback,...)
Definition: sorcery.c:82
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:1511
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:2288
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:520
#define TYPE_BUCKETS
Number of buckets for types (should be prime for performance reasons)
Definition: sorcery.c:54
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2475
struct ast_sorcery * __ast_sorcery_open(const char *module_name, const char *file, int line, const char *func)
Definition: sorcery.c:601
static int sorcery_observers_notify_loaded(void *data)
Internal callback function which notifies observers that an object type has been loaded.
Definition: sorcery.c:1326
static int is_registered_cb(void *obj, void *arg, int flags)
Definition: sorcery.c:2500
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:1897
static void sorcery_object_field_destructor(void *obj)
Definition: sorcery.c:1150
static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
Definition: sorcery.c:298
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:1114
struct ast_sorcery * ast_sorcery_retrieve_by_module_name(const char *module_name)
Search function for sorcery instances.
Definition: sorcery.c:672
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
Delete an object.
Definition: sorcery.c:2238
void * ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
Create a copy of an object.
Definition: sorcery.c:1778
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:1989
int ast_sorcery_init(void)
Compare function for sorcery instances.
Definition: sorcery.c:387
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:700
static void sorcery_object_wizard_destructor(void *obj)
Object wizard destructor.
Definition: sorcery.c:762
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:869
static void sorcery_internal_wizard_destructor(void *obj)
Definition: sorcery.c:425
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:1139
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
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
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
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:89
struct ao2_container * observers
Observers.
Definition: sorcery.c:99
struct ast_sorcery_wizard callbacks
Wizard interface itself.
Definition: sorcery.c:96
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:205
regex_t * name_regex
The compiled name regex if name is a regex.
Definition: sorcery.c:210
sorcery_field_handler handler
Callback function for translation of a single value.
Definition: sorcery.c:213
sorcery_fields_handler multiple_handler
Callback function for translation of multiple values.
Definition: sorcery.c:216
intptr_t args[]
Position of the field.
Definition: sorcery.c:219
char name[MAX_OBJECT_FIELD]
Name of the field.
Definition: sorcery.c:207
Structure for registered object type observer.
Definition: sorcery.c:190
const struct ast_sorcery_observer * callbacks
Pointer to the observer implementation.
Definition: sorcery.c:192
Structure for registered object type.
Definition: sorcery.c:148
sorcery_copy_handler copy
Optional object copy callback.
Definition: sorcery.c:159
struct aco_file * file
Configuration framework file information.
Definition: sorcery.c:174
struct ast_sorcery_object_wizards wizards
Wizard instances.
Definition: sorcery.c:165
sorcery_transform_handler transform
Optional transformation callback.
Definition: sorcery.c:153
struct ao2_container * fields
Object fields.
Definition: sorcery.c:168
char name[MAX_OBJECT_TYPE]
Unique name of the object type.
Definition: sorcery.c:150
sorcery_diff_handler diff
Optional object diff callback.
Definition: sorcery.c:162
sorcery_apply_handler apply
Optional object set apply callback.
Definition: sorcery.c:156
struct ao2_container * observers
Observers.
Definition: sorcery.c:180
struct ast_taskprocessor * serializer
Serializer for observers.
Definition: sorcery.c:183
struct aco_type type
Type details.
Definition: sorcery.c:177
unsigned int reloadable
Specifies if object type is reloadable or not.
Definition: sorcery.c:186
struct aco_info * info
Configuration framework general information.
Definition: sorcery.c:171
Structure for a wizard instance which operates on objects.
Definition: sorcery.c:103
unsigned int caching
Wizard is acting as an object cache.
Definition: sorcery.c:111
struct ast_sorcery_internal_wizard * wizard
Wizard interface itself.
Definition: sorcery.c:105
void * data
Unique data for the wizard.
Definition: sorcery.c:108
unsigned int allow_duplicates
Wizard allows others of the same type.
Definition: sorcery.c:117
char wizard_args[0]
Wizard arguments.
Definition: sorcery.c:120
unsigned int read_only
Wizard is read_only.
Definition: sorcery.c:114
Structure for internal sorcery object information.
Definition: sorcery.c:127
unsigned int has_dynamic_contents
Whether this object has dynamic contents or not.
Definition: sorcery.c:144
struct timeval created
Time that the object was created.
Definition: sorcery.c:141
ao2_destructor_fn destructor
Optional object destructor.
Definition: sorcery.c:135
struct ast_variable * extended
Extended object fields.
Definition: sorcery.c:138
char type[MAX_OBJECT_TYPE]
Type of object.
Definition: sorcery.c:132
char * id
Unique identifier of this object.
Definition: sorcery.c:129
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:230
char * module_name
Pointer to module_name in the associated sorcery_proxy.
Definition: sorcery.c:238
struct ao2_container * observers
Observers.
Definition: sorcery.c:235
struct ao2_container * types
Container for known object types.
Definition: sorcery.c:232
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:1831
void * obj
Pointer to the object itself.
Definition: sorcery.c:1835
const struct ast_sorcery * sorcery
Pointer to the sorcery instance.
Definition: sorcery.c:1833
A global observer wrapper.
Definition: sorcery.c:266
const struct ast_sorcery_global_observer * callbacks
Definition: sorcery.c:267
An instance observer wrapper.
Definition: sorcery.c:271
const struct ast_sorcery_instance_observer * callbacks
Definition: sorcery.c:272
Structure for passing load/reload details.
Definition: sorcery.c:242
unsigned int force
Whether this is forced or not.
Definition: sorcery.c:253
const char * type
Type of object being loaded.
Definition: sorcery.c:247
unsigned int reload
Whether this is a reload or not.
Definition: sorcery.c:250
const struct ast_sorcery * sorcery
Sorcery structure in use.
Definition: sorcery.c:244
Structure used for observer invocations.
Definition: sorcery.c:196
void * object
Pointer to the object.
Definition: sorcery.c:201
struct ast_sorcery_object_type * object_type
Pointer to the object type.
Definition: sorcery.c:198
Proxy object for sorcery.
Definition: sorcery.c:223
char module_name[0]
The name of the module owning this sorcery instance.
Definition: sorcery.c:226
A wizard observer wrapper.
Definition: sorcery.c:276
const struct ast_sorcery_wizard_observer * callbacks
Definition: sorcery.c:277
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
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:71
struct ast_taskprocessor * ast_threadpool_serializer(const char *name, struct ast_threadpool *pool)
Serialized execution of tasks within a ast_threadpool.
Definition: threadpool.c:1428
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:941
#define ast_assert(a)
Definition: utils.h:739
#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:448
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:609
#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:338
#define AST_VECTOR_RW_WRLOCK(vec)
Obtain write lock on vector.
Definition: vector.h:887
#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:540
#define AST_VECTOR_RW_UNLOCK(vec)
Unlock vector.
Definition: vector.h:897
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
Definition: vector.h:731
#define AST_VECTOR_RW_FREE(vec)
Deallocates this locked vector.
Definition: vector.h:202
#define AST_VECTOR_CALLBACK(vec, callback, default_value,...)
Execute a callback on every element in a vector returning the first matched.
Definition: vector.h:765
#define AST_VECTOR_RW_RDLOCK(vec)
Obtain read lock on vector.
Definition: vector.h:877
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:862
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:680
#define AST_VECTOR_RW_INIT(vec, size)
Initialize a vector with a read/write lock.
Definition: vector.h:158