2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2012 - 2013, Digium, Inc.
6 * Joshua Colp <jcolp@digium.com>
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.
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.
21 * \brief Sorcery Data Access Layer API
23 * \author Joshua Colp <jcolp@digium.com>
27 <support_level>core</support_level>
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
34 #include "asterisk/logger.h"
35 #include "asterisk/sorcery.h"
36 #include "asterisk/astobj2.h"
37 #include "asterisk/format.h"
38 #include "asterisk/format_cap.h"
39 #include "asterisk/strings.h"
40 #include "asterisk/config_options.h"
41 #include "asterisk/netsock2.h"
42 #include "asterisk/module.h"
43 #include "asterisk/taskprocessor.h"
44 #include "asterisk/threadpool.h"
45 #include "asterisk/json.h"
47 /* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
51 /*! \brief Number of buckets for wizards (should be prime for performance reasons) */
52 #define WIZARD_BUCKETS 7
54 /*! \brief Number of buckets for types (should be prime for performance reasons) */
55 #define TYPE_BUCKETS 53
57 /*! \brief Number of buckets for instances (should be prime for performance reasons) */
58 #define INSTANCE_BUCKETS 17
60 /*! \brief Number of buckets for object fields (should be prime for performance reasons) */
61 #define OBJECT_FIELD_BUCKETS 29
63 #define NOTIFY_GENERIC_OBSERVERS(container, type, callback, ...) ({ \
64 struct ao2_iterator i = ao2_iterator_init(container, 0); \
65 struct type *observer; \
66 ao2_rdlock(container); \
67 while ((observer = ao2_iterator_next(&i))) { \
68 if (observer->callbacks->callback) { \
69 observer->callbacks->callback(__VA_ARGS__); \
71 ao2_cleanup(observer); \
73 ao2_unlock(container); \
74 ao2_iterator_cleanup(&i); \
77 #define NOTIFY_GLOBAL_OBSERVERS(container, callback, ...) \
78 NOTIFY_GENERIC_OBSERVERS(container, sorcery_global_observer, callback, __VA_ARGS__)
80 #define NOTIFY_INSTANCE_OBSERVERS(container, callback, ...) \
81 NOTIFY_GENERIC_OBSERVERS(container, sorcery_instance_observer, callback, __VA_ARGS__)
83 #define NOTIFY_WIZARD_OBSERVERS(container, callback, ...) \
84 NOTIFY_GENERIC_OBSERVERS(container, sorcery_wizard_observer, callback, __VA_ARGS__)
86 /*! \brief Thread pool for observers */
87 static struct ast_threadpool *threadpool;
89 /*! \brief Structure for internal sorcery object information */
90 struct ast_sorcery_object {
91 /*! \brief Unique identifier of this object */
94 /*! \brief Type of object */
95 char type[MAX_OBJECT_TYPE];
97 /*! \brief Optional object destructor */
98 ao2_destructor_fn destructor;
100 /*! \brief Extended object fields */
101 struct ast_variable *extended;
104 /*! \brief Structure for registered object type */
105 struct ast_sorcery_object_type {
106 /*! \brief Unique name of the object type */
107 char name[MAX_OBJECT_TYPE];
109 /*! \brief Optional transformation callback */
110 sorcery_transform_handler transform;
112 /*! \brief Optional object set apply callback */
113 sorcery_apply_handler apply;
115 /*! \brief Optional object copy callback */
116 sorcery_copy_handler copy;
118 /*! \brief Optional object diff callback */
119 sorcery_diff_handler diff;
121 /*! \brief Wizard instances */
122 struct ao2_container *wizards;
124 /*! \brief Object fields */
125 struct ao2_container *fields;
127 /*! \brief Configuration framework general information */
128 struct aco_info *info;
130 /*! \brief Configuration framework file information */
131 struct aco_file *file;
133 /*! \brief Type details */
134 struct aco_type type;
136 /*! \brief Observers */
137 struct ao2_container *observers;
139 /*! \brief Serializer for observers */
140 struct ast_taskprocessor *serializer;
142 /*! \brief Specifies if object type is reloadable or not */
143 unsigned int reloadable:1;
146 /*! \brief Structure for registered object type observer */
147 struct ast_sorcery_object_type_observer {
148 /*! \brief Pointer to the observer implementation */
149 const struct ast_sorcery_observer *callbacks;
152 /*! \brief Structure used for observer invocations */
153 struct sorcery_observer_invocation {
154 /*! \brief Pointer to the object type */
155 struct ast_sorcery_object_type *object_type;
157 /*! \brief Pointer to the object */
161 /*! \brief Structure for registered object field */
162 struct ast_sorcery_object_field {
163 /*! \brief Name of the field */
164 char name[MAX_OBJECT_FIELD];
166 /*! \brief The compiled name regex if name is a regex */
169 /*! \brief Callback function for translation of a single value */
170 sorcery_field_handler handler;
172 /*! \brief Callback function for translation of multiple values */
173 sorcery_fields_handler multiple_handler;
175 /*! \brief Position of the field */
179 /*! \brief Structure for an internal wizard instance */
180 struct ast_sorcery_internal_wizard {
181 /*! \brief Wizard interface itself */
182 struct ast_sorcery_wizard callbacks;
184 /*! \brief Observers */
185 struct ao2_container *observers;
188 /*! \brief Structure for a wizard instance which operates on objects */
189 struct ast_sorcery_object_wizard {
190 /*! \brief Wizard interface itself */
191 struct ast_sorcery_internal_wizard *wizard;
193 /*! \brief Unique data for the wizard */
196 /*! \brief Wizard is acting as an object cache */
197 unsigned int caching:1;
200 /*! \brief Full structure for sorcery */
202 /*! \brief Container for known object types */
203 struct ao2_container *types;
205 /*! \brief Observers */
206 struct ao2_container *observers;
208 /*! \brief The name of the module owning this sorcery instance */
212 /*! \brief Structure for passing load/reload details */
213 struct sorcery_load_details {
214 /*! \brief Sorcery structure in use */
215 const struct ast_sorcery *sorcery;
217 /*! \brief Type of object being loaded */
220 /*! \brief Whether this is a reload or not */
221 unsigned int reload:1;
224 /*! \brief Registered sorcery wizards */
225 static struct ao2_container *wizards;
227 /* The following 3 observer wrappers must name their
228 * external observer 'callbacks' and it must be
229 * the first member of the structure. Common macros
230 * and container callbacks depend on it.
233 /*! \brief A global observer wrapper */
234 struct sorcery_global_observer {
235 const struct ast_sorcery_global_observer *callbacks;
238 /*! \brief An instance observer wrapper */
239 struct sorcery_instance_observer {
240 const struct ast_sorcery_instance_observer *callbacks;
243 /*! \brief A wizard observer wrapper */
244 struct sorcery_wizard_observer {
245 const struct ast_sorcery_wizard_observer *callbacks;
248 /*! \brief Registered global observers */
249 struct ao2_container *observers;
251 /*! \brief Registered sorcery instances */
252 static struct ao2_container *instances;
254 static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
256 int *field = (int *)(obj + args[0]);
257 return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
260 static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
262 unsigned int *field = (unsigned int *)(obj + args[0]);
263 return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
266 static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
268 double *field = (double *)(obj + args[0]);
269 return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
272 static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
274 ast_string_field *field = (const char **)(obj + args[0]);
275 return !(*buf = ast_strdup(*field)) ? -1 : 0;
278 static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
280 unsigned int *field = (unsigned int *)(obj + args[0]);
281 return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
284 static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
286 struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
287 return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
290 static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
292 char *field = (char *)(obj + args[0]);
293 return !(*buf = ast_strdup(field)) ? -1 : 0;
296 static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
298 struct ast_str *codec_buf = ast_str_alloca(64);
299 struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
300 return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
303 static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
306 case OPT_BOOL_T: return bool_handler_fn;
307 case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
308 case OPT_CODEC_T: return codec_handler_fn;
309 case OPT_DOUBLE_T: return double_handler_fn;
310 case OPT_INT_T: return int_handler_fn;
311 case OPT_SOCKADDR_T: return sockaddr_handler_fn;
312 case OPT_STRINGFIELD_T: return stringfield_handler_fn;
313 case OPT_UINT_T: return uint_handler_fn;
316 case OPT_CUSTOM_T: return NULL;
322 /*! \brief Hashing function for sorcery wizards */
323 static int sorcery_wizard_hash(const void *obj, const int flags)
325 const struct ast_sorcery_internal_wizard *object;
328 switch (flags & OBJ_SEARCH_MASK) {
332 case OBJ_SEARCH_OBJECT:
334 key = object->callbacks.name;
340 return ast_str_hash(key);
343 /*! \brief Comparator function for sorcery wizards */
344 static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
346 const struct ast_sorcery_internal_wizard *object_left = obj;
347 const struct ast_sorcery_internal_wizard *object_right = arg;
348 const char *right_key = arg;
351 switch (flags & OBJ_SEARCH_MASK) {
352 case OBJ_SEARCH_OBJECT:
353 right_key = object_right->callbacks.name;
356 cmp = strcmp(object_left->callbacks.name, right_key);
358 case OBJ_SEARCH_PARTIAL_KEY:
359 cmp = strncmp(object_left->callbacks.name, right_key, strlen(right_key));
371 /*! \brief Hashing function for sorcery wizards */
372 static int object_type_field_hash(const void *obj, const int flags)
374 const struct ast_sorcery_object_field *object_field;
377 switch (flags & OBJ_SEARCH_MASK) {
381 case OBJ_SEARCH_OBJECT:
383 key = object_field->name;
389 return ast_str_hash(key);
392 static int object_type_field_cmp(void *obj, void *arg, int flags)
394 const struct ast_sorcery_object_field *field_left = obj;
395 const struct ast_sorcery_object_field *field_right = arg;
396 const char *right_key = arg;
399 switch (flags & OBJ_SEARCH_MASK) {
400 case OBJ_SEARCH_OBJECT:
401 right_key = field_right->name;
404 cmp = strcmp(field_left->name, right_key);
406 case OBJ_SEARCH_PARTIAL_KEY:
407 cmp = strncmp(field_left->name, right_key, strlen(right_key));
419 /*! \brief Cleanup function */
420 static void sorcery_exit(void)
422 ast_threadpool_shutdown(threadpool);
426 /*! \brief Cleanup function for graceful shutdowns */
427 static void sorcery_cleanup(void)
429 ao2_cleanup(wizards);
431 ao2_cleanup(observers);
433 ao2_cleanup(instances);
437 /*! \brief Compare function for sorcery instances */
438 static int sorcery_instance_cmp(void *obj, void *arg, int flags)
440 const struct ast_sorcery *object_left = obj;
441 const struct ast_sorcery *object_right = arg;
442 const char *right_key = arg;
445 switch (flags & OBJ_SEARCH_MASK) {
446 case OBJ_SEARCH_OBJECT:
447 right_key = object_right->module_name;
450 cmp = strcmp(object_left->module_name, right_key);
452 case OBJ_SEARCH_PARTIAL_KEY:
453 cmp = strncmp(object_left->module_name, right_key, strlen(right_key));
465 /*! \brief Hashing function for sorcery instances */
466 static int sorcery_instance_hash(const void *obj, const int flags)
468 const struct ast_sorcery *object;
471 switch (flags & OBJ_SEARCH_MASK) {
475 case OBJ_SEARCH_OBJECT:
477 key = object->module_name;
483 return ast_str_hash(key);
486 int ast_sorcery_init(void)
488 struct ast_threadpool_options options = {
489 .version = AST_THREADPOOL_OPTIONS_VERSION,
495 ast_assert(wizards == NULL);
497 if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
502 if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
503 ast_threadpool_shutdown(threadpool);
507 observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
514 instances = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, INSTANCE_BUCKETS,
515 sorcery_instance_hash, sorcery_instance_cmp);
522 ast_register_cleanup(sorcery_cleanup);
523 ast_register_atexit(sorcery_exit);
528 static void sorcery_internal_wizard_destructor(void *obj)
530 struct ast_sorcery_internal_wizard *wizard = obj;
532 ao2_cleanup(wizard->observers);
535 int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
537 struct ast_sorcery_internal_wizard *wizard;
540 ast_assert(!ast_strlen_zero(interface->name));
544 if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
545 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
550 if (!(wizard = ao2_alloc(sizeof(*wizard), sorcery_internal_wizard_destructor))) {
554 wizard->callbacks = *interface;
555 wizard->callbacks.module = module;
557 wizard->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
558 if (!wizard->observers) {
562 ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
565 ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
567 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_registered,
568 interface->name, interface);
577 int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
579 struct ast_sorcery_internal_wizard *wizard =
580 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL;
583 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_unregistering, wizard->callbacks.name, &wizard->callbacks);
584 ao2_unlink(wizards, wizard);
586 ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
593 /*! \brief Internal callback function for removing a generic observer */
594 static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
596 const struct sorcery_global_observer *observer = obj;
598 return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
601 int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
603 struct sorcery_global_observer *cb;
605 cb = ao2_alloc(sizeof(*cb), NULL);
610 cb->callbacks = callbacks;
611 ao2_link(observers, cb);
617 void ast_sorcery_global_observer_remove(
618 const struct ast_sorcery_global_observer *callbacks)
620 ao2_callback(observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
623 int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery,
624 const struct ast_sorcery_instance_observer *callbacks)
626 struct sorcery_instance_observer *cb;
628 cb = ao2_alloc(sizeof(*cb), NULL);
633 cb->callbacks = callbacks;
634 ao2_link(sorcery->observers, cb);
640 void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery,
641 const struct ast_sorcery_instance_observer *callbacks)
643 ao2_callback(sorcery->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
646 int ast_sorcery_wizard_observer_add(struct ast_sorcery_wizard *interface,
647 const struct ast_sorcery_wizard_observer *callbacks)
649 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
650 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
654 struct sorcery_wizard_observer *cb;
656 cb = ao2_alloc(sizeof(*cb), NULL);
661 cb->callbacks = callbacks;
662 ao2_link(wizard->observers, cb);
671 void ast_sorcery_wizard_observer_remove(struct ast_sorcery_wizard *interface,
672 const struct ast_sorcery_wizard_observer *callbacks)
674 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
675 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
679 ao2_callback(wizard->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
683 /*! \brief Destructor called when sorcery structure is destroyed */
684 static void sorcery_destructor(void *obj)
686 struct ast_sorcery *sorcery = obj;
688 if (sorcery->observers) {
689 NOTIFY_GLOBAL_OBSERVERS(observers, instance_destroying, sorcery->module_name, sorcery);
691 ao2_cleanup(sorcery->observers);
692 ao2_cleanup(sorcery->types);
695 /*! \brief Hashing function for sorcery types */
696 static int sorcery_type_hash(const void *obj, const int flags)
698 const struct ast_sorcery_object_type *object;
701 switch (flags & OBJ_SEARCH_MASK) {
705 case OBJ_SEARCH_OBJECT:
713 return ast_str_hash(key);
716 /*! \brief Comparator function for sorcery types */
717 static int sorcery_type_cmp(void *obj, void *arg, int flags)
719 const struct ast_sorcery_object_type *object_left = obj;
720 const struct ast_sorcery_object_type *object_right = arg;
721 const char *right_key = arg;
724 switch (flags & OBJ_SEARCH_MASK) {
725 case OBJ_SEARCH_OBJECT:
726 right_key = object_right->name;
729 cmp = strcmp(object_left->name, right_key);
731 case OBJ_SEARCH_PARTIAL_KEY:
732 cmp = strncmp(object_left->name, right_key, strlen(right_key));
744 struct ast_sorcery *__ast_sorcery_open(const char *module_name)
746 struct ast_sorcery *sorcery;
748 ast_assert(module_name != NULL);
750 ao2_wrlock(instances);
751 if ((sorcery = ao2_find(instances, module_name, OBJ_SEARCH_KEY | OBJ_NOLOCK))) {
755 if (!(sorcery = ao2_alloc(sizeof(*sorcery) + strlen(module_name) + 1, sorcery_destructor))) {
759 if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
760 ao2_ref(sorcery, -1);
765 if (!(sorcery->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL))) {
766 ao2_ref(sorcery, -1);
771 strcpy(sorcery->module_name, module_name); /* Safe */
773 if (__ast_sorcery_apply_config(sorcery, module_name, module_name) == AST_SORCERY_APPLY_FAIL) {
774 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
775 ao2_cleanup(sorcery);
780 ao2_link_flags(instances, sorcery, OBJ_NOLOCK);
782 NOTIFY_GLOBAL_OBSERVERS(observers, instance_created, module_name, sorcery);
785 ao2_unlock(instances);
789 /*! \brief Search function for sorcery instances */
790 struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name)
792 return ao2_find(instances, module_name, OBJ_SEARCH_KEY);
795 /*! \brief Destructor function for object types */
796 static void sorcery_object_type_destructor(void *obj)
798 struct ast_sorcery_object_type *object_type = obj;
800 ao2_cleanup(object_type->wizards);
801 ao2_cleanup(object_type->fields);
802 ao2_cleanup(object_type->observers);
804 if (object_type->info) {
805 aco_info_destroy(object_type->info);
806 ast_free(object_type->info);
809 ast_free(object_type->file);
811 ast_taskprocessor_unreference(object_type->serializer);
814 /*! \brief Internal function which allocates an object type structure */
815 static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
817 struct ast_sorcery_object_type *object_type;
818 char uuid[AST_UUID_STR_LEN];
820 if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
824 /* Order matters for object wizards */
825 if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, sorcery_wizard_cmp))) {
826 ao2_ref(object_type, -1);
830 if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, OBJECT_FIELD_BUCKETS,
831 object_type_field_hash, object_type_field_cmp))) {
832 ao2_ref(object_type, -1);
836 if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
837 ao2_ref(object_type, -1);
841 if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
842 ao2_ref(object_type, -1);
846 if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
847 ao2_ref(object_type, -1);
851 if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
852 ao2_ref(object_type, -1);
856 if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
857 ao2_ref(object_type, -1);
861 object_type->info->files[0] = object_type->file;
862 object_type->info->files[1] = NULL;
863 object_type->info->module = module;
865 ast_copy_string(object_type->name, type, sizeof(object_type->name));
870 /*! \brief Object wizard destructor */
871 static void sorcery_object_wizard_destructor(void *obj)
873 struct ast_sorcery_object_wizard *object_wizard = obj;
875 if (object_wizard->data) {
876 object_wizard->wizard->callbacks.close(object_wizard->data);
879 if (object_wizard->wizard) {
880 ast_module_unref(object_wizard->wizard->callbacks.module);
883 ao2_cleanup(object_wizard->wizard);
886 /*! \brief Internal function which creates an object type and adds a wizard mapping */
887 enum ast_sorcery_apply_result __ast_sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
888 const char *type, const char *module, const char *name, const char *data, unsigned int caching)
890 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
891 RAII_VAR(struct ast_sorcery_internal_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
892 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
896 ast_log(LOG_ERROR, "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
898 return AST_SORCERY_APPLY_FAIL;
899 } else if (!object_wizard) {
900 return AST_SORCERY_APPLY_FAIL;
904 if (!(object_type = sorcery_object_type_alloc(type, module))) {
905 return AST_SORCERY_APPLY_FAIL;
911 struct ast_sorcery_wizard *found;
913 found = ao2_find(object_type->wizards, wizard, OBJ_SEARCH_OBJECT);
915 ast_debug(1, "Wizard %s already applied to object type %s\n",
916 wizard->callbacks.name, object_type->name);
918 return AST_SORCERY_APPLY_DUPLICATE;
922 if (wizard->callbacks.open && !(object_wizard->data = wizard->callbacks.open(data))) {
923 return AST_SORCERY_APPLY_FAIL;
926 ast_module_ref(wizard->callbacks.module);
928 object_wizard->wizard = ao2_bump(wizard);
929 object_wizard->caching = caching;
931 ao2_link(object_type->wizards, object_wizard);
934 ao2_link(sorcery->types, object_type);
937 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, wizard_mapped,
938 sorcery->module_name, sorcery, type, &wizard->callbacks, data, object_wizard->data);
940 return AST_SORCERY_APPLY_SUCCESS;
943 enum ast_sorcery_apply_result __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
945 struct ast_flags flags = { 0 };
946 struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
947 struct ast_variable *mapping;
948 int res = AST_SORCERY_APPLY_SUCCESS;
951 return AST_SORCERY_APPLY_NO_CONFIGURATION;
954 if (config == CONFIG_STATUS_FILEINVALID) {
955 return AST_SORCERY_APPLY_FAIL;
958 for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
959 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
960 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
961 char *options = mapping_name;
962 char *type = strsep(&options, "/");
963 char *data = mapping_value;
964 char *wizard = strsep(&data, ",");
965 unsigned int caching = 0;
967 /* If no object type or wizard exists just skip, nothing we can do */
968 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
972 /* If the wizard is configured as a cache treat it as such */
973 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
977 /* Any error immediately causes us to stop */
978 if (__ast_sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
979 res = AST_SORCERY_APPLY_FAIL;
984 ast_config_destroy(config);
989 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)
991 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
993 /* Defaults can not be added if any existing mapping exists */
995 return AST_SORCERY_APPLY_DEFAULT_UNNECESSARY;
998 return __ast_sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
1001 static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
1003 return ast_sorcery_object_set_extended(obj, var->name, var->value);
1006 static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
1008 const struct ast_sorcery_object_details *details = obj;
1010 if (details->object->extended) {
1011 *fields = ast_variables_dup(details->object->extended);
1019 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)
1021 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1023 if (!object_type || object_type->type.item_alloc) {
1027 object_type->type.name = object_type->name;
1028 object_type->type.type = ACO_ITEM;
1029 object_type->type.category = ".?";
1030 object_type->type.item_alloc = alloc;
1031 object_type->type.hidden = hidden;
1033 object_type->reloadable = reloadable;
1034 object_type->transform = transform;
1035 object_type->apply = apply;
1036 object_type->file->types[0] = &object_type->type;
1037 object_type->file->types[1] = NULL;
1039 if (aco_info_init(object_type->info)) {
1043 if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
1047 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, object_type_registered,
1048 sorcery->module_name, sorcery, type);
1053 void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
1055 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1061 object_type->copy = copy;
1064 void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
1066 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1072 object_type->diff = diff;
1075 static void sorcery_object_field_destructor(void *obj)
1077 struct ast_sorcery_object_field *object_field = obj;
1079 if (object_field->name_regex) {
1080 regfree(object_field->name_regex);
1081 ast_free(object_field->name_regex);
1085 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)
1087 #define MAX_REGEX_ERROR_LEN 128
1088 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1089 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1092 if (!object_type || !object_type->type.item_alloc || !config_handler
1093 || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
1097 ast_copy_string(object_field->name, regex, sizeof(object_field->name));
1098 object_field->multiple_handler = sorcery_handler;
1100 if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
1104 if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
1105 char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
1106 regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
1107 ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
1111 ao2_link(object_type->fields, object_field);
1112 __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
1117 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,
1118 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, ...)
1120 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1121 RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1125 if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
1129 if (!sorcery_handler) {
1130 sorcery_handler = sorcery_field_default_handler(opt_type);
1133 if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
1137 ast_copy_string(object_field->name, name, sizeof(object_field->name));
1138 object_field->handler = sorcery_handler;
1139 object_field->multiple_handler = multiple_handler;
1141 va_start(args, argc);
1142 for (pos = 0; pos < argc; pos++) {
1143 object_field->args[pos] = va_arg(args, size_t);
1148 ao2_link(object_type->fields, object_field);
1151 /* TODO: Improve this hack */
1153 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
1154 } else if (argc == 1) {
1155 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1156 object_field->args[0]);
1157 } else if (argc == 2) {
1158 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1159 object_field->args[0], object_field->args[1]);
1160 } else if (argc == 3) {
1161 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1162 object_field->args[0], object_field->args[1], object_field->args[2]);
1164 ast_assert(0); /* The hack... she does us no good for this */
1170 /*! \brief Retrieves whether or not the type is reloadable */
1171 static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
1173 RAII_VAR(struct ast_sorcery_object_type *, object_type,
1174 ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1175 return object_type && object_type->reloadable;
1178 static int sorcery_wizard_load(void *obj, void *arg, int flags)
1180 struct ast_sorcery_object_wizard *wizard = obj;
1181 struct sorcery_load_details *details = arg;
1182 void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
1184 load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload;
1187 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
1188 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1190 load(wizard->data, details->sorcery, details->type);
1192 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loaded,
1193 wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1199 /*! \brief Destructor for observer invocation */
1200 static void sorcery_observer_invocation_destroy(void *obj)
1202 struct sorcery_observer_invocation *invocation = obj;
1204 ao2_cleanup(invocation->object_type);
1205 ao2_cleanup(invocation->object);
1208 /*! \brief Allocator function for observer invocation */
1209 static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
1211 struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
1217 ao2_ref(object_type, +1);
1218 invocation->object_type = object_type;
1221 ao2_ref(object, +1);
1222 invocation->object = object;
1228 /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1229 static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1231 const struct ast_sorcery_object_type_observer *observer = obj;
1233 if (observer->callbacks->loaded) {
1234 observer->callbacks->loaded(arg);
1240 /*! \brief Internal callback function which notifies observers that an object type has been loaded */
1241 static int sorcery_observers_notify_loaded(void *data)
1243 struct sorcery_observer_invocation *invocation = data;
1245 ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
1246 ao2_cleanup(invocation);
1251 static int sorcery_object_load(void *obj, void *arg, int flags)
1253 struct ast_sorcery_object_type *type = obj;
1254 struct sorcery_load_details *details = arg;
1256 if (!type->type.item_alloc) {
1260 details->type = type->name;
1262 if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
1263 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
1268 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
1269 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1271 ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
1273 NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
1274 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1276 if (ao2_container_count(type->observers)) {
1277 struct sorcery_observer_invocation *invocation;
1279 invocation = sorcery_observer_invocation_alloc(type, NULL);
1281 && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded,
1283 ao2_cleanup(invocation);
1290 void ast_sorcery_load(const struct ast_sorcery *sorcery)
1292 struct sorcery_load_details details = {
1297 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1298 sorcery->module_name, sorcery, 0);
1300 ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1302 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
1303 sorcery->module_name, sorcery, 0);
1306 void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1308 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1309 struct sorcery_load_details details = {
1318 sorcery_object_load(object_type, &details, 0);
1321 void ast_sorcery_reload(const struct ast_sorcery *sorcery)
1323 struct sorcery_load_details details = {
1328 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1329 sorcery->module_name, sorcery, 1);
1331 ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1333 NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
1334 sorcery->module_name, sorcery, 1);
1338 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1340 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1341 struct sorcery_load_details details = {
1350 sorcery_object_load(object_type, &details, 0);
1353 void ast_sorcery_ref(struct ast_sorcery *sorcery)
1355 ao2_ref(sorcery, +1);
1358 static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1360 struct ast_variable *tmp = NULL;
1363 if (!object_field->handler) {
1367 if (!(object_field->handler(object, object_field->args, &buf))) {
1368 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1375 static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1377 struct ast_variable *tmp = NULL;
1379 if (!object_field->multiple_handler) {
1383 if (object_field->multiple_handler(object, &tmp)) {
1384 ast_variables_destroy(tmp);
1391 struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
1392 const void *object, enum ast_sorcery_field_handler_flags flags)
1394 const struct ast_sorcery_object_details *details = object;
1395 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1396 struct ao2_iterator i;
1397 struct ast_sorcery_object_field *object_field;
1398 struct ast_variable *head = NULL;
1399 struct ast_variable *tail = NULL;
1405 i = ao2_iterator_init(object_type->fields, 0);
1407 for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1408 struct ast_variable *tmp;
1411 case AST_HANDLER_PREFER_LIST:
1412 if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1413 (tmp = get_single_field_as_var_list(object, object_field))) {
1417 case AST_HANDLER_PREFER_STRING:
1418 if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1419 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1423 case AST_HANDLER_ONLY_LIST:
1424 if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1428 case AST_HANDLER_ONLY_STRING:
1429 if ((tmp = get_single_field_as_var_list(object, object_field))) {
1437 tail = ast_variable_list_append_hint(&head, tail, tmp);
1440 ao2_iterator_destroy(&i);
1445 struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1447 const struct ast_sorcery_object_details *details = object;
1448 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1449 struct ao2_iterator i;
1450 struct ast_sorcery_object_field *object_field;
1451 struct ast_json *json = ast_json_object_create();
1454 if (!object_type || !json) {
1458 i = ao2_iterator_init(object_type->fields, 0);
1460 for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1461 if (object_field->multiple_handler) {
1462 struct ast_variable *tmp = NULL;
1463 struct ast_variable *field;
1465 if ((res = object_field->multiple_handler(object, &tmp))) {
1466 ast_variables_destroy(tmp);
1467 ao2_ref(object_field, -1);
1471 for (field = tmp; field; field = field->next) {
1472 struct ast_json *value = ast_json_string_create(field->value);
1474 if (!value || ast_json_object_set(json, field->name, value)) {
1480 ast_variables_destroy(tmp);
1481 } else if (object_field->handler) {
1483 struct ast_json *value = NULL;
1485 if ((res = object_field->handler(object, object_field->args, &buf))
1486 || !(value = ast_json_string_create(buf))
1487 || ast_json_object_set(json, object_field->name, value)) {
1497 ao2_iterator_destroy(&i);
1499 /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1501 ast_json_unref(json);
1508 int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1510 const struct ast_sorcery_object_details *details = object;
1511 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1512 RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1513 struct ast_variable *field;
1520 if (object_type->transform && (transformed = object_type->transform(objectset))) {
1521 field = transformed;
1526 for (; field; field = field->next) {
1527 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1532 if (!res && object_type->apply) {
1533 res = object_type->apply(sorcery, object);
1539 int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1541 const struct ast_variable *field;
1546 /* Unless the ast_variable list changes when examined... it can't differ from itself */
1547 if (original == modified) {
1551 for (field = modified; field; field = field->next) {
1552 const char *old_value = ast_variable_find_in_list(original, field->name);
1554 if (!old_value || strcmp(old_value, field->value)) {
1555 struct ast_variable *tmp;
1557 if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1562 tmp->next = *changes;
1567 /* If an error occurred do not return a partial changeset */
1569 ast_variables_destroy(*changes);
1576 static void sorcery_object_destructor(void *object)
1578 struct ast_sorcery_object_details *details = object;
1580 if (details->object->destructor) {
1581 details->object->destructor(object);
1584 ast_variables_destroy(details->object->extended);
1585 ast_free(details->object->id);
1588 void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1590 void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
1591 struct ast_sorcery_object_details *details = object;
1597 details->object = object + size;
1598 details->object->destructor = destructor;
1603 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1605 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1606 struct ast_sorcery_object_details *details;
1608 if (!object_type || !object_type->type.item_alloc ||
1609 !(details = object_type->type.item_alloc(id))) {
1613 if (ast_strlen_zero(id)) {
1614 char uuid[AST_UUID_STR_LEN];
1616 ast_uuid_generate_str(uuid, sizeof(uuid));
1617 details->object->id = ast_strdup(uuid);
1619 details->object->id = ast_strdup(id);
1622 ast_copy_string(details->object->type, type, sizeof(details->object->type));
1624 if (aco_set_defaults(&object_type->type, id, details)) {
1625 ao2_ref(details, -1);
1632 void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
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 struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
1637 RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1642 } else if (object_type->copy) {
1643 res = object_type->copy(object, copy);
1644 } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1645 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1647 /* No native copy available and could not create an objectset, this copy has failed */
1659 int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1661 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
1665 if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1669 if (original == modified) {
1671 } else if (!object_type->diff) {
1672 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1673 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1675 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1676 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1678 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1680 return object_type->diff(original, modified, changes);
1684 /*! \brief Structure used when calling create, update, or delete */
1685 struct sorcery_details {
1686 /*! \brief Pointer to the sorcery instance */
1687 const struct ast_sorcery *sorcery;
1688 /*! \brief Pointer to the object itself */
1692 /*! \brief Internal function used to create an object in caching wizards */
1693 static int sorcery_cache_create(void *obj, void *arg, int flags)
1695 const struct ast_sorcery_object_wizard *object_wizard = obj;
1696 const struct sorcery_details *details = arg;
1698 if (!object_wizard->caching || !object_wizard->wizard->callbacks.create) {
1702 object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj);
1707 void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1709 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1710 void *object = NULL;
1711 struct ao2_iterator i;
1712 struct ast_sorcery_object_wizard *wizard;
1713 unsigned int cached = 0;
1715 if (!object_type || ast_strlen_zero(id)) {
1719 i = ao2_iterator_init(object_type->wizards, 0);
1720 for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1721 if (wizard->wizard->callbacks.retrieve_id &&
1722 !(object = wizard->wizard->callbacks.retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1726 cached = wizard->caching;
1728 ao2_ref(wizard, -1);
1731 ao2_iterator_destroy(&i);
1733 if (!cached && object) {
1734 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1740 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1742 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1743 void *object = NULL;
1744 struct ao2_iterator i;
1745 struct ast_sorcery_object_wizard *wizard;
1746 unsigned int cached = 0;
1752 /* If returning multiple objects create a container to store them in */
1753 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1754 if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1759 /* Inquire with the available wizards for retrieval */
1760 i = ao2_iterator_init(object_type->wizards, 0);
1761 for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1762 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1763 if (wizard->wizard->callbacks.retrieve_multiple) {
1764 wizard->wizard->callbacks.retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1766 } else if (fields && wizard->wizard->callbacks.retrieve_fields) {
1767 if (wizard->wizard->callbacks.retrieve_fields) {
1768 object = wizard->wizard->callbacks.retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1772 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
1776 cached = wizard->caching;
1778 ao2_ref(wizard, -1);
1781 ao2_iterator_destroy(&i);
1783 /* If we are returning a single object and it came from a non-cache source create it in any caches */
1784 if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1785 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1791 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1793 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1794 struct ao2_container *objects;
1795 struct ao2_iterator i;
1796 struct ast_sorcery_object_wizard *wizard;
1798 if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1802 i = ao2_iterator_init(object_type->wizards, 0);
1803 for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1804 if (!wizard->wizard->callbacks.retrieve_regex) {
1808 wizard->wizard->callbacks.retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1810 ao2_iterator_destroy(&i);
1815 /*! \brief Internal function which returns if the wizard has created the object */
1816 static int sorcery_wizard_create(void *obj, void *arg, int flags)
1818 const struct ast_sorcery_object_wizard *object_wizard = obj;
1819 const struct sorcery_details *details = arg;
1821 if (!object_wizard->wizard->callbacks.create) {
1823 ast_log(LOG_ERROR, "Sorcery wizard '%s' doesn't contain a 'create' virtual function.\n",
1824 object_wizard->wizard->callbacks.name);
1827 return (!object_wizard->caching && !object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
1830 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
1831 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
1833 const struct ast_sorcery_object_type_observer *observer = obj;
1835 if (observer->callbacks->created) {
1836 observer->callbacks->created(arg);
1842 /*! \brief Internal callback function which notifies observers that an object has been created */
1843 static int sorcery_observers_notify_create(void *data)
1845 struct sorcery_observer_invocation *invocation = data;
1847 ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
1848 ao2_cleanup(invocation);
1853 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
1855 const struct ast_sorcery_object_details *details = object;
1856 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1857 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1858 struct sorcery_details sdetails = {
1867 if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
1868 ao2_container_count(object_type->observers)) {
1869 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1871 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
1872 ao2_cleanup(invocation);
1876 return object_wizard ? 0 : -1;
1879 /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
1880 static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
1882 const struct ast_sorcery_object_type_observer *observer = obj;
1884 if (observer->callbacks->updated) {
1885 observer->callbacks->updated(arg);
1891 /*! \brief Internal callback function which notifies observers that an object has been updated */
1892 static int sorcery_observers_notify_update(void *data)
1894 struct sorcery_observer_invocation *invocation = data;
1896 ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
1897 ao2_cleanup(invocation);
1902 /*! \brief Internal function which returns if a wizard has updated the object */
1903 static int sorcery_wizard_update(void *obj, void *arg, int flags)
1905 const struct ast_sorcery_object_wizard *object_wizard = obj;
1906 const struct sorcery_details *details = arg;
1908 return (object_wizard->wizard->callbacks.update && !object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj) &&
1909 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1912 int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
1914 const struct ast_sorcery_object_details *details = object;
1915 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1916 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1917 struct sorcery_details sdetails = {
1926 if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
1927 ao2_container_count(object_type->observers)) {
1928 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1930 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
1931 ao2_cleanup(invocation);
1935 return object_wizard ? 0 : -1;
1938 /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
1939 static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
1941 const struct ast_sorcery_object_type_observer *observer = obj;
1943 if (observer->callbacks->deleted) {
1944 observer->callbacks->deleted(arg);
1950 /*! \brief Internal callback function which notifies observers that an object has been deleted */
1951 static int sorcery_observers_notify_delete(void *data)
1953 struct sorcery_observer_invocation *invocation = data;
1955 ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
1956 ao2_cleanup(invocation);
1961 /*! \brief Internal function which returns if a wizard has deleted the object */
1962 static int sorcery_wizard_delete(void *obj, void *arg, int flags)
1964 const struct ast_sorcery_object_wizard *object_wizard = obj;
1965 const struct sorcery_details *details = arg;
1967 return (object_wizard->wizard->callbacks.delete && !object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj) &&
1968 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1971 int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
1973 const struct ast_sorcery_object_details *details = object;
1974 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1975 RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1976 struct sorcery_details sdetails = {
1985 if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
1986 ao2_container_count(object_type->observers)) {
1987 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1989 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
1990 ao2_cleanup(invocation);
1994 return object_wizard ? 0 : -1;
1997 void ast_sorcery_unref(struct ast_sorcery *sorcery)
2000 /* One ref for what we just released, the other for the instances container. */
2001 ao2_wrlock(instances);
2002 if (ao2_ref(sorcery, -1) == 2) {
2003 ao2_unlink_flags(instances, sorcery, OBJ_NOLOCK);
2005 ao2_unlock(instances);
2009 const char *ast_sorcery_object_get_id(const void *object)
2011 const struct ast_sorcery_object_details *details = object;
2012 return details->object->id;
2015 const char *ast_sorcery_object_get_type(const void *object)
2017 const struct ast_sorcery_object_details *details = object;
2018 return details->object->type;
2021 const char *ast_sorcery_object_get_extended(const void *object, const char *name)
2023 const struct ast_sorcery_object_details *details = object;
2024 struct ast_variable *field;
2026 for (field = details->object->extended; field; field = field->next) {
2027 if (!strcmp(field->name + 1, name)) {
2028 return field->value;
2035 int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
2037 RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
2038 struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
2039 const struct ast_sorcery_object_details *details = object;
2045 for (field = details->object->extended; field; previous = field, field = field->next) {
2046 if (!strcmp(field->name, name)) {
2048 previous->next = field->next;
2050 details->object->extended = field->next;
2057 extended->next = details->object->extended;
2058 details->object->extended = extended;
2063 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
2065 RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
2066 struct ast_sorcery_object_type_observer *observer;
2069 if (!object_type || !callbacks) {
2073 if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
2077 observer->callbacks = callbacks;
2079 if (!ao2_link(object_type->observers, observer)) {
2082 ao2_ref(observer, -1);
2087 /*! \brief Internal callback function for removing an observer */
2088 static int sorcery_observer_remove(void *obj, void *arg, int flags)
2090 const struct ast_sorcery_object_type_observer *observer = obj;
2092 return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
2095 void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
2097 RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
2098 struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
2103 object_type = ao2_find(sorcery->types, type, OBJ_KEY);
2108 ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
2109 sorcery_observer_remove, cbs);
2112 int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
2114 const char *right_key = arg;
2117 switch (flags & OBJ_SEARCH_MASK) {
2118 case OBJ_SEARCH_OBJECT:
2119 right_key = ast_sorcery_object_get_id(arg);
2121 case OBJ_SEARCH_KEY:
2122 cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
2124 case OBJ_SEARCH_PARTIAL_KEY:
2125 cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
2134 int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
2136 const char *right_key = arg;
2139 switch (flags & OBJ_SEARCH_MASK) {
2140 case OBJ_SEARCH_OBJECT:
2141 right_key = ast_sorcery_object_get_id(arg);
2143 case OBJ_SEARCH_KEY:
2144 if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
2145 cmp = CMP_MATCH | CMP_STOP;
2148 case OBJ_SEARCH_PARTIAL_KEY:
2149 if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
2160 int ast_sorcery_object_id_hash(const void *obj, int flags) {
2161 if (flags & OBJ_SEARCH_OBJECT) {
2162 return ast_str_hash(ast_sorcery_object_get_id(obj));
2163 } else if (flags & OBJ_SEARCH_KEY) {
2164 return ast_str_hash(obj);
2169 struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
2172 return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
2175 static int is_registered_cb(void *obj, void *arg, int flags)
2177 struct ast_sorcery_object_field *object_field = obj;
2181 if (object_field->name_regex
2182 && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
2183 rc = CMP_MATCH | CMP_STOP;
2189 int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
2190 const char *field_name)
2192 struct ast_sorcery_object_field *object_field;
2195 ast_assert(object_type != NULL);
2197 object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
2199 if (!object_field) {
2200 object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
2203 if (!object_field) {
2207 ao2_cleanup(object_field);