Replace most uses of ast_register_atexit with ast_register_cleanup.
[asterisk/asterisk.git] / main / sorcery.c
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 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
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"
46
47 /* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
48 #undef open
49 #undef close
50
51 /*! \brief Number of buckets for wizards (should be prime for performance reasons) */
52 #define WIZARD_BUCKETS 7
53
54 /*! \brief Number of buckets for types (should be prime for performance reasons) */
55 #define TYPE_BUCKETS 53
56
57 /*! \brief Number of buckets for instances (should be prime for performance reasons) */
58 #define INSTANCE_BUCKETS 17
59
60 /*! \brief Number of buckets for object fields (should be prime for performance reasons) */
61 #define OBJECT_FIELD_BUCKETS 29
62
63 #define NOTIFY_GENERIC_OBSERVERS(container, type, callback, ...) ({ \
64         struct ao2_iterator i = ao2_iterator_init(container, 0); \
65         struct type *observer; \
66         ao2_rdlock(container); \
67         while ((observer = ao2_iterator_next(&i))) { \
68                 if (observer->callbacks->callback) { \
69                         observer->callbacks->callback(__VA_ARGS__); \
70                 } \
71                 ao2_cleanup(observer); \
72         } \
73         ao2_unlock(container); \
74         ao2_iterator_cleanup(&i); \
75 })
76
77 #define NOTIFY_GLOBAL_OBSERVERS(container, callback, ...) \
78         NOTIFY_GENERIC_OBSERVERS(container, sorcery_global_observer, callback, __VA_ARGS__)
79
80 #define NOTIFY_INSTANCE_OBSERVERS(container, callback, ...) \
81         NOTIFY_GENERIC_OBSERVERS(container, sorcery_instance_observer, callback, __VA_ARGS__)
82
83 #define NOTIFY_WIZARD_OBSERVERS(container, callback, ...) \
84         NOTIFY_GENERIC_OBSERVERS(container, sorcery_wizard_observer, callback, __VA_ARGS__)
85
86 /*! \brief Thread pool for observers */
87 static struct ast_threadpool *threadpool;
88
89 /*! \brief Structure for internal sorcery object information */
90 struct ast_sorcery_object {
91         /*! \brief Unique identifier of this object */
92         char *id;
93
94         /*! \brief Type of object */
95         char type[MAX_OBJECT_TYPE];
96
97         /*! \brief Optional object destructor */
98         ao2_destructor_fn destructor;
99
100         /*! \brief Extended object fields */
101         struct ast_variable *extended;
102 };
103
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];
108
109         /*! \brief Optional transformation callback */
110         sorcery_transform_handler transform;
111
112         /*! \brief Optional object set apply callback */
113         sorcery_apply_handler apply;
114
115         /*! \brief Optional object copy callback */
116         sorcery_copy_handler copy;
117
118         /*! \brief Optional object diff callback */
119         sorcery_diff_handler diff;
120
121         /*! \brief Wizard instances */
122         struct ao2_container *wizards;
123
124         /*! \brief Object fields */
125         struct ao2_container *fields;
126
127         /*! \brief Configuration framework general information */
128         struct aco_info *info;
129
130         /*! \brief Configuration framework file information */
131         struct aco_file *file;
132
133         /*! \brief Type details */
134         struct aco_type type;
135
136         /*! \brief Observers */
137         struct ao2_container *observers;
138
139         /*! \brief Serializer for observers */
140         struct ast_taskprocessor *serializer;
141
142         /*! \brief Specifies if object type is reloadable or not */
143         unsigned int reloadable:1;
144 };
145
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;
150 };
151
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;
156
157         /*! \brief Pointer to the object */
158         void *object;
159 };
160
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];
165
166         /*! \brief The compiled name regex if name is a regex */
167         regex_t *name_regex;
168
169         /*! \brief Callback function for translation of a single value */
170         sorcery_field_handler handler;
171
172         /*! \brief Callback function for translation of multiple values */
173         sorcery_fields_handler multiple_handler;
174
175         /*! \brief Position of the field */
176         intptr_t args[];
177 };
178
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;
183
184         /*! \brief Observers */
185         struct ao2_container *observers;
186 };
187
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;
192
193         /*! \brief Unique data for the wizard */
194         void *data;
195
196         /*! \brief Wizard is acting as an object cache */
197         unsigned int caching:1;
198 };
199
200 /*! \brief Full structure for sorcery */
201 struct ast_sorcery {
202         /*! \brief Container for known object types */
203         struct ao2_container *types;
204
205         /*! \brief Observers */
206         struct ao2_container *observers;
207
208         /*! \brief The name of the module owning this sorcery instance */
209         char module_name[0];
210 };
211
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;
216
217         /*! \brief Type of object being loaded */
218         const char *type;
219
220         /*! \brief Whether this is a reload or not */
221         unsigned int reload:1;
222 };
223
224 /*! \brief Registered sorcery wizards */
225 static struct ao2_container *wizards;
226
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.
231  */
232
233 /*! \brief A global observer wrapper */
234 struct sorcery_global_observer {
235         const struct ast_sorcery_global_observer *callbacks;
236 };
237
238 /*! \brief An instance observer wrapper */
239 struct sorcery_instance_observer {
240         const struct ast_sorcery_instance_observer *callbacks;
241 };
242
243 /*! \brief A wizard observer wrapper */
244 struct sorcery_wizard_observer {
245         const struct ast_sorcery_wizard_observer *callbacks;
246 };
247
248 /*! \brief Registered global observers */
249 struct ao2_container *observers;
250
251 /*! \brief Registered sorcery instances */
252 static struct ao2_container *instances;
253
254 static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
255 {
256         int *field = (int *)(obj + args[0]);
257         return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
258 }
259
260 static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
261 {
262         unsigned int *field = (unsigned int *)(obj + args[0]);
263         return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
264 }
265
266 static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
267 {
268         double *field = (double *)(obj + args[0]);
269         return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
270 }
271
272 static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
273 {
274         ast_string_field *field = (const char **)(obj + args[0]);
275         return !(*buf = ast_strdup(*field)) ? -1 : 0;
276 }
277
278 static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
279 {
280         unsigned int *field = (unsigned int *)(obj + args[0]);
281         return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
282 }
283
284 static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
285 {
286         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
287         return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
288 }
289
290 static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
291 {
292         char *field = (char *)(obj + args[0]);
293         return !(*buf = ast_strdup(field)) ? -1 : 0;
294 }
295
296 static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
297 {
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)));
301 }
302
303 static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
304 {
305         switch(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;
314
315         default:
316         case OPT_CUSTOM_T: return NULL;
317         }
318
319         return NULL;
320 }
321
322 /*! \brief Hashing function for sorcery wizards */
323 static int sorcery_wizard_hash(const void *obj, const int flags)
324 {
325         const struct ast_sorcery_internal_wizard *object;
326         const char *key;
327
328         switch (flags & OBJ_SEARCH_MASK) {
329         case OBJ_SEARCH_KEY:
330                 key = obj;
331                 break;
332         case OBJ_SEARCH_OBJECT:
333                 object = obj;
334                 key = object->callbacks.name;
335                 break;
336         default:
337                 ast_assert(0);
338                 return 0;
339         }
340         return ast_str_hash(key);
341 }
342
343 /*! \brief Comparator function for sorcery wizards */
344 static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
345 {
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;
349         int cmp;
350
351         switch (flags & OBJ_SEARCH_MASK) {
352         case OBJ_SEARCH_OBJECT:
353                 right_key = object_right->callbacks.name;
354                 /* Fall through */
355         case OBJ_SEARCH_KEY:
356                 cmp = strcmp(object_left->callbacks.name, right_key);
357                 break;
358         case OBJ_SEARCH_PARTIAL_KEY:
359                 cmp = strncmp(object_left->callbacks.name, right_key, strlen(right_key));
360                 break;
361         default:
362                 cmp = 0;
363                 break;
364         }
365         if (cmp) {
366                 return 0;
367         }
368         return CMP_MATCH;
369 }
370
371 /*! \brief Hashing function for sorcery wizards */
372 static int object_type_field_hash(const void *obj, const int flags)
373 {
374         const struct ast_sorcery_object_field *object_field;
375         const char *key;
376
377         switch (flags & OBJ_SEARCH_MASK) {
378         case OBJ_SEARCH_KEY:
379                 key = obj;
380                 break;
381         case OBJ_SEARCH_OBJECT:
382                 object_field = obj;
383                 key = object_field->name;
384                 break;
385         default:
386                 ast_assert(0);
387                 return 0;
388         }
389         return ast_str_hash(key);
390 }
391
392 static int object_type_field_cmp(void *obj, void *arg, int flags)
393 {
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;
397         int cmp;
398
399         switch (flags & OBJ_SEARCH_MASK) {
400         case OBJ_SEARCH_OBJECT:
401                 right_key = field_right->name;
402                 /* Fall through */
403         case OBJ_SEARCH_KEY:
404                 cmp = strcmp(field_left->name, right_key);
405                 break;
406         case OBJ_SEARCH_PARTIAL_KEY:
407                 cmp = strncmp(field_left->name, right_key, strlen(right_key));
408                 break;
409         default:
410                 cmp = 0;
411                 break;
412         }
413         if (cmp) {
414                 return 0;
415         }
416         return CMP_MATCH;
417 }
418
419 /*! \brief Cleanup function for graceful shutdowns */
420 static void sorcery_cleanup(void)
421 {
422         ast_threadpool_shutdown(threadpool);
423         threadpool = NULL;
424         ao2_cleanup(wizards);
425         wizards = NULL;
426         ao2_cleanup(observers);
427         observers = NULL;
428         ao2_cleanup(instances);
429         instances = NULL;
430 }
431
432 /*! \brief Compare function for sorcery instances */
433 static int sorcery_instance_cmp(void *obj, void *arg, int flags)
434 {
435         const struct ast_sorcery *object_left = obj;
436         const struct ast_sorcery *object_right = arg;
437         const char *right_key = arg;
438         int cmp;
439
440         switch (flags & OBJ_SEARCH_MASK) {
441         case OBJ_SEARCH_OBJECT:
442                 right_key = object_right->module_name;
443                 /* Fall through */
444         case OBJ_SEARCH_KEY:
445                 cmp = strcmp(object_left->module_name, right_key);
446                 break;
447         case OBJ_SEARCH_PARTIAL_KEY:
448                 cmp = strncmp(object_left->module_name, right_key, strlen(right_key));
449                 break;
450         default:
451                 cmp = 0;
452                 break;
453         }
454         if (cmp) {
455                 return 0;
456         }
457         return CMP_MATCH;
458 }
459
460 /*! \brief Hashing function for sorcery instances */
461 static int sorcery_instance_hash(const void *obj, const int flags)
462 {
463         const struct ast_sorcery *object;
464         const char *key;
465
466         switch (flags & OBJ_SEARCH_MASK) {
467         case OBJ_SEARCH_KEY:
468                 key = obj;
469                 break;
470         case OBJ_SEARCH_OBJECT:
471                 object = obj;
472                 key = object->module_name;
473                 break;
474         default:
475                 ast_assert(0);
476                 return 0;
477         }
478         return ast_str_hash(key);
479 }
480
481 int ast_sorcery_init(void)
482 {
483         struct ast_threadpool_options options = {
484                 .version = AST_THREADPOOL_OPTIONS_VERSION,
485                 .auto_increment = 1,
486                 .max_size = 0,
487                 .idle_timeout = 60,
488                 .initial_size = 0,
489         };
490         ast_assert(wizards == NULL);
491
492         if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
493                 threadpool = NULL;
494                 return -1;
495         }
496
497         if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
498                 ast_threadpool_shutdown(threadpool);
499                 return -1;
500         }
501
502         observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
503         if (!observers) {
504                 sorcery_cleanup();
505                 return -1;
506         }
507
508         instances = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, INSTANCE_BUCKETS,
509                 sorcery_instance_hash, sorcery_instance_cmp);
510         if (!instances) {
511                 sorcery_cleanup();
512                 return -1;
513         }
514
515         ast_register_cleanup(sorcery_cleanup);
516
517         return 0;
518 }
519
520 static void sorcery_internal_wizard_destructor(void *obj)
521 {
522         struct ast_sorcery_internal_wizard *wizard = obj;
523
524         ao2_cleanup(wizard->observers);
525 }
526
527 int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
528 {
529         struct ast_sorcery_internal_wizard *wizard;
530         int res = -1;
531
532         ast_assert(!ast_strlen_zero(interface->name));
533
534         ao2_lock(wizards);
535
536         if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
537                 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
538                         interface->name);
539                 goto done;
540         }
541
542         if (!(wizard = ao2_alloc(sizeof(*wizard), sorcery_internal_wizard_destructor))) {
543                 goto done;
544         }
545
546         wizard->callbacks = *interface;
547         wizard->callbacks.module = module;
548
549         wizard->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL);
550         if (!wizard->observers) {
551                 goto done;
552         }
553
554         ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
555         res = 0;
556
557         ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
558
559         NOTIFY_GLOBAL_OBSERVERS(observers, wizard_registered,
560                 interface->name, interface);
561
562 done:
563         ao2_cleanup(wizard);
564         ao2_unlock(wizards);
565
566         return res;
567 }
568
569 int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
570 {
571         struct ast_sorcery_internal_wizard *wizard =
572                 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL;
573
574         if (wizard) {
575                 NOTIFY_GLOBAL_OBSERVERS(observers, wizard_unregistering, wizard->callbacks.name, &wizard->callbacks);
576                 ao2_unlink(wizards, wizard);
577                 ao2_ref(wizard, -1);
578                 ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
579                 return 0;
580         } else {
581                 return -1;
582         }
583 }
584
585 /*! \brief Internal callback function for removing a generic observer */
586 static int sorcery_generic_observer_remove(void *obj, void *arg, int flags)
587 {
588         const struct sorcery_global_observer *observer = obj;
589
590         return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
591 }
592
593 int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks)
594 {
595         struct sorcery_global_observer *cb;
596
597         cb = ao2_alloc(sizeof(*cb), NULL);
598         if (!cb) {
599                 return -1;
600         }
601
602         cb->callbacks = callbacks;
603         ao2_link(observers, cb);
604         ao2_ref(cb, -1);
605
606         return 0;
607 }
608
609 void ast_sorcery_global_observer_remove(
610         const struct ast_sorcery_global_observer *callbacks)
611 {
612         ao2_callback(observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
613 }
614
615 int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery,
616         const struct ast_sorcery_instance_observer *callbacks)
617 {
618         struct sorcery_instance_observer *cb;
619
620         cb = ao2_alloc(sizeof(*cb), NULL);
621         if (!cb) {
622                 return -1;
623         }
624
625         cb->callbacks = callbacks;
626         ao2_link(sorcery->observers, cb);
627         ao2_ref(cb, -1);
628
629         return 0;
630 }
631
632 void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery,
633         const struct ast_sorcery_instance_observer *callbacks)
634 {
635         ao2_callback(sorcery->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
636 }
637
638 int ast_sorcery_wizard_observer_add(struct ast_sorcery_wizard *interface,
639         const struct ast_sorcery_wizard_observer *callbacks)
640 {
641         RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
642                 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
643                         ao2_cleanup);
644
645         if (wizard) {
646                 struct sorcery_wizard_observer *cb;
647
648                 cb = ao2_alloc(sizeof(*cb), NULL);
649                 if (!cb) {
650                         return -1;
651                 }
652
653                 cb->callbacks = callbacks;
654                 ao2_link(wizard->observers, cb);
655                 ao2_ref(cb, -1);
656
657                 return 0;
658         }
659
660         return -1;
661 }
662
663 void ast_sorcery_wizard_observer_remove(struct ast_sorcery_wizard *interface,
664         const struct ast_sorcery_wizard_observer *callbacks)
665 {
666         RAII_VAR(struct ast_sorcery_internal_wizard *, wizard,
667                 interface ? ao2_find(wizards, interface->name, OBJ_SEARCH_KEY) : NULL,
668                         ao2_cleanup);
669
670         if (wizard) {
671                 ao2_callback(wizard->observers, OBJ_NODATA | OBJ_UNLINK, sorcery_generic_observer_remove, (void *)callbacks);
672         }
673 }
674
675 /*! \brief Destructor called when sorcery structure is destroyed */
676 static void sorcery_destructor(void *obj)
677 {
678         struct ast_sorcery *sorcery = obj;
679
680         if (sorcery->observers) {
681                 NOTIFY_GLOBAL_OBSERVERS(observers, instance_destroying, sorcery->module_name, sorcery);
682         }
683         ao2_cleanup(sorcery->observers);
684         ao2_cleanup(sorcery->types);
685 }
686
687 /*! \brief Hashing function for sorcery types */
688 static int sorcery_type_hash(const void *obj, const int flags)
689 {
690         const struct ast_sorcery_object_type *object;
691         const char *key;
692
693         switch (flags & OBJ_SEARCH_MASK) {
694         case OBJ_SEARCH_KEY:
695                 key = obj;
696                 break;
697         case OBJ_SEARCH_OBJECT:
698                 object = obj;
699                 key = object->name;
700                 break;
701         default:
702                 ast_assert(0);
703                 return 0;
704         }
705         return ast_str_hash(key);
706 }
707
708 /*! \brief Comparator function for sorcery types */
709 static int sorcery_type_cmp(void *obj, void *arg, int flags)
710 {
711         const struct ast_sorcery_object_type *object_left = obj;
712         const struct ast_sorcery_object_type *object_right = arg;
713         const char *right_key = arg;
714         int cmp;
715
716         switch (flags & OBJ_SEARCH_MASK) {
717         case OBJ_SEARCH_OBJECT:
718                 right_key = object_right->name;
719                 /* Fall through */
720         case OBJ_SEARCH_KEY:
721                 cmp = strcmp(object_left->name, right_key);
722                 break;
723         case OBJ_SEARCH_PARTIAL_KEY:
724                 cmp = strncmp(object_left->name, right_key, strlen(right_key));
725                 break;
726         default:
727                 cmp = 0;
728                 break;
729         }
730         if (cmp) {
731                 return 0;
732         }
733         return CMP_MATCH;
734 }
735
736 struct ast_sorcery *__ast_sorcery_open(const char *module_name)
737 {
738         struct ast_sorcery *sorcery;
739
740         ast_assert(module_name != NULL);
741
742         ao2_wrlock(instances);
743         if ((sorcery = ao2_find(instances, module_name, OBJ_SEARCH_KEY | OBJ_NOLOCK))) {
744                 goto done;
745         }
746
747         if (!(sorcery = ao2_alloc(sizeof(*sorcery) + strlen(module_name) + 1, sorcery_destructor))) {
748                 goto done;
749         }
750
751         if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
752                 ao2_ref(sorcery, -1);
753                 sorcery = NULL;
754                 goto done;
755         }
756
757         if (!(sorcery->observers = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_RWLOCK, 0, NULL, NULL))) {
758                 ao2_ref(sorcery, -1);
759                 sorcery = NULL;
760                 goto done;
761         }
762
763         strcpy(sorcery->module_name, module_name); /* Safe */
764
765         if (__ast_sorcery_apply_config(sorcery, module_name, module_name) == AST_SORCERY_APPLY_FAIL) {
766                 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
767                 ao2_cleanup(sorcery);
768                 sorcery = NULL;
769                 goto done;
770         }
771
772         ao2_link_flags(instances, sorcery, OBJ_NOLOCK);
773
774         NOTIFY_GLOBAL_OBSERVERS(observers, instance_created, module_name, sorcery);
775
776 done:
777         ao2_unlock(instances);
778         return sorcery;
779 }
780
781 /*! \brief Search function for sorcery instances */
782 struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name)
783 {
784         return ao2_find(instances, module_name, OBJ_SEARCH_KEY);
785 }
786
787 /*! \brief Destructor function for object types */
788 static void sorcery_object_type_destructor(void *obj)
789 {
790         struct ast_sorcery_object_type *object_type = obj;
791
792         ao2_cleanup(object_type->wizards);
793         ao2_cleanup(object_type->fields);
794         ao2_cleanup(object_type->observers);
795
796         if (object_type->info) {
797                 aco_info_destroy(object_type->info);
798                 ast_free(object_type->info);
799         }
800
801         ast_free(object_type->file);
802
803         ast_taskprocessor_unreference(object_type->serializer);
804 }
805
806 /*! \brief Internal function which allocates an object type structure */
807 static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
808 {
809         struct ast_sorcery_object_type *object_type;
810         char uuid[AST_UUID_STR_LEN];
811
812         if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
813                 return NULL;
814         }
815
816         /* Order matters for object wizards */
817         if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, sorcery_wizard_cmp))) {
818                 ao2_ref(object_type, -1);
819                 return NULL;
820         }
821
822         if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, OBJECT_FIELD_BUCKETS,
823                                         object_type_field_hash, object_type_field_cmp))) {
824                 ao2_ref(object_type, -1);
825                 return NULL;
826         }
827
828         if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
829                 ao2_ref(object_type, -1);
830                 return NULL;
831         }
832
833         if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
834                 ao2_ref(object_type, -1);
835                 return NULL;
836         }
837
838         if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
839                 ao2_ref(object_type, -1);
840                 return NULL;
841         }
842
843         if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
844                 ao2_ref(object_type, -1);
845                 return NULL;
846         }
847
848         if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
849                 ao2_ref(object_type, -1);
850                 return NULL;
851         }
852
853         object_type->info->files[0] = object_type->file;
854         object_type->info->files[1] = NULL;
855         object_type->info->module = module;
856
857         ast_copy_string(object_type->name, type, sizeof(object_type->name));
858
859         return object_type;
860 }
861
862 /*! \brief Object wizard destructor */
863 static void sorcery_object_wizard_destructor(void *obj)
864 {
865         struct ast_sorcery_object_wizard *object_wizard = obj;
866
867         if (object_wizard->data) {
868                 object_wizard->wizard->callbacks.close(object_wizard->data);
869         }
870
871         if (object_wizard->wizard) {
872                 ast_module_unref(object_wizard->wizard->callbacks.module);
873         }
874
875         ao2_cleanup(object_wizard->wizard);
876 }
877
878 /*! \brief Internal function which creates an object type and adds a wizard mapping */
879 enum ast_sorcery_apply_result __ast_sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
880                 const char *type, const char *module, const char *name, const char *data, unsigned int caching)
881 {
882         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
883         RAII_VAR(struct ast_sorcery_internal_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
884         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
885         int created = 0;
886
887         if (!wizard) {
888                 ast_log(LOG_ERROR, "Wizard '%s' could not be applied to object type '%s' as it was not found\n",
889                         name, type);
890                 return AST_SORCERY_APPLY_FAIL;
891         } else if (!object_wizard) {
892                 return AST_SORCERY_APPLY_FAIL;
893         }
894
895         if (!object_type) {
896                 if (!(object_type = sorcery_object_type_alloc(type, module))) {
897                         return AST_SORCERY_APPLY_FAIL;
898                 }
899                 created = 1;
900         }
901
902         if (!created) {
903                 struct ast_sorcery_wizard *found;
904
905                 found = ao2_find(object_type->wizards, wizard, OBJ_SEARCH_OBJECT);
906                 if (found) {
907                         ast_debug(1, "Wizard %s already applied to object type %s\n",
908                                         wizard->callbacks.name, object_type->name);
909                         ao2_cleanup(found);
910                         return AST_SORCERY_APPLY_DUPLICATE;
911                 }
912         }
913
914         if (wizard->callbacks.open && !(object_wizard->data = wizard->callbacks.open(data))) {
915                 return AST_SORCERY_APPLY_FAIL;
916         }
917
918         ast_module_ref(wizard->callbacks.module);
919
920         object_wizard->wizard = ao2_bump(wizard);
921         object_wizard->caching = caching;
922
923         ao2_link(object_type->wizards, object_wizard);
924
925         if (created) {
926                 ao2_link(sorcery->types, object_type);
927         }
928
929         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, wizard_mapped,
930                 sorcery->module_name, sorcery, type, &wizard->callbacks, data, object_wizard->data);
931
932         return AST_SORCERY_APPLY_SUCCESS;
933 }
934
935 enum ast_sorcery_apply_result  __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
936 {
937         struct ast_flags flags = { 0 };
938         struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
939         struct ast_variable *mapping;
940         int res = AST_SORCERY_APPLY_SUCCESS;
941
942         if (!config) {
943                 return AST_SORCERY_APPLY_NO_CONFIGURATION;
944         }
945
946         if (config == CONFIG_STATUS_FILEINVALID) {
947                 return AST_SORCERY_APPLY_FAIL;
948         }
949
950         for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
951                 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
952                 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
953                 char *options = mapping_name;
954                 char *type = strsep(&options, "/");
955                 char *data = mapping_value;
956                 char *wizard = strsep(&data, ",");
957                 unsigned int caching = 0;
958
959                 /* If no object type or wizard exists just skip, nothing we can do */
960                 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
961                         continue;
962                 }
963
964                 /* If the wizard is configured as a cache treat it as such */
965                 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
966                         caching = 1;
967                 }
968
969                 /* Any error immediately causes us to stop */
970                 if (__ast_sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
971                         res = AST_SORCERY_APPLY_FAIL;
972                         break;
973                 }
974         }
975
976         ast_config_destroy(config);
977
978         return res;
979 }
980
981 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)
982 {
983         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
984
985         /* Defaults can not be added if any existing mapping exists */
986         if (object_type) {
987                 return AST_SORCERY_APPLY_DEFAULT_UNNECESSARY;
988         }
989
990         return __ast_sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
991 }
992
993 static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
994 {
995         return ast_sorcery_object_set_extended(obj, var->name, var->value);
996 }
997
998 static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
999 {
1000         const struct ast_sorcery_object_details *details = obj;
1001
1002         if (details->object->extended) {
1003                 *fields = ast_variables_dup(details->object->extended);
1004         } else {
1005                 *fields = NULL;
1006         }
1007
1008         return 0;
1009 }
1010
1011 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)
1012 {
1013         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1014
1015         if (!object_type || object_type->type.item_alloc) {
1016                 return -1;
1017         }
1018
1019         object_type->type.name = object_type->name;
1020         object_type->type.type = ACO_ITEM;
1021         object_type->type.category = ".?";
1022         object_type->type.item_alloc = alloc;
1023         object_type->type.hidden = hidden;
1024
1025         object_type->reloadable = reloadable;
1026         object_type->transform = transform;
1027         object_type->apply = apply;
1028         object_type->file->types[0] = &object_type->type;
1029         object_type->file->types[1] = NULL;
1030
1031         if (aco_info_init(object_type->info)) {
1032                 return -1;
1033         }
1034
1035         if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
1036                 return -1;
1037         }
1038
1039         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, object_type_registered,
1040                 sorcery->module_name, sorcery, type);
1041
1042         return 0;
1043 }
1044
1045 void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
1046 {
1047         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1048
1049         if (!object_type) {
1050                 return;
1051         }
1052
1053         object_type->copy = copy;
1054 }
1055
1056 void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
1057 {
1058         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1059
1060         if (!object_type) {
1061                 return;
1062         }
1063
1064         object_type->diff = diff;
1065 }
1066
1067 static void sorcery_object_field_destructor(void *obj)
1068 {
1069         struct ast_sorcery_object_field *object_field = obj;
1070
1071         if (object_field->name_regex) {
1072                 regfree(object_field->name_regex);
1073                 ast_free(object_field->name_regex);
1074         }
1075 }
1076
1077 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)
1078 {
1079 #define MAX_REGEX_ERROR_LEN 128
1080         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1081         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1082         int rc;
1083
1084         if (!object_type || !object_type->type.item_alloc || !config_handler
1085                 || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
1086                 return -1;
1087         }
1088
1089         ast_copy_string(object_field->name, regex, sizeof(object_field->name));
1090         object_field->multiple_handler = sorcery_handler;
1091
1092         if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
1093                 return -1;
1094         }
1095
1096         if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
1097                 char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
1098                 regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
1099                 ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
1100                 return -1;
1101         }
1102
1103         ao2_link(object_type->fields, object_field);
1104         __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
1105
1106         return 0;
1107 }
1108
1109 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,
1110                                         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, ...)
1111 {
1112         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1113         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
1114         int pos;
1115         va_list args;
1116
1117         if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
1118                 return -1;
1119         }
1120
1121         if (!sorcery_handler) {
1122                 sorcery_handler = sorcery_field_default_handler(opt_type);
1123         }
1124
1125         if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
1126                 return -1;
1127         }
1128
1129         ast_copy_string(object_field->name, name, sizeof(object_field->name));
1130         object_field->handler = sorcery_handler;
1131         object_field->multiple_handler = multiple_handler;
1132
1133         va_start(args, argc);
1134         for (pos = 0; pos < argc; pos++) {
1135                 object_field->args[pos] = va_arg(args, size_t);
1136         }
1137         va_end(args);
1138
1139         if (!alias) {
1140                 ao2_link(object_type->fields, object_field);
1141         }
1142
1143         /* TODO: Improve this hack */
1144         if (!argc) {
1145                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
1146         } else if (argc == 1) {
1147                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1148                         object_field->args[0]);
1149         } else if (argc == 2) {
1150                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
1151                         object_field->args[0], object_field->args[1]);
1152         } else if (argc == 3) {
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                         object_field->args[0], object_field->args[1], object_field->args[2]);
1155         } else {
1156                 ast_assert(0); /* The hack... she does us no good for this */
1157         }
1158
1159         return 0;
1160 }
1161
1162 /*! \brief Retrieves whether or not the type is reloadable */
1163 static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
1164 {
1165         RAII_VAR(struct ast_sorcery_object_type *, object_type,
1166                  ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1167         return object_type && object_type->reloadable;
1168 }
1169
1170 static int sorcery_wizard_load(void *obj, void *arg, int flags)
1171 {
1172         struct ast_sorcery_object_wizard *wizard = obj;
1173         struct sorcery_load_details *details = arg;
1174         void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
1175
1176         load = !details->reload ? wizard->wizard->callbacks.load : wizard->wizard->callbacks.reload;
1177
1178         if (load) {
1179                 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loading,
1180                         wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1181
1182                 load(wizard->data, details->sorcery, details->type);
1183
1184                 NOTIFY_WIZARD_OBSERVERS(wizard->wizard->observers, wizard_loaded,
1185                         wizard->wizard->callbacks.name, &wizard->wizard->callbacks, details->type, details->reload);
1186         }
1187
1188         return 0;
1189 }
1190
1191 /*! \brief Destructor for observer invocation */
1192 static void sorcery_observer_invocation_destroy(void *obj)
1193 {
1194         struct sorcery_observer_invocation *invocation = obj;
1195
1196         ao2_cleanup(invocation->object_type);
1197         ao2_cleanup(invocation->object);
1198 }
1199
1200 /*! \brief Allocator function for observer invocation */
1201 static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
1202 {
1203         struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
1204
1205         if (!invocation) {
1206                 return NULL;
1207         }
1208
1209         ao2_ref(object_type, +1);
1210         invocation->object_type = object_type;
1211
1212         if (object) {
1213                 ao2_ref(object, +1);
1214                 invocation->object = object;
1215         }
1216
1217         return invocation;
1218 }
1219
1220 /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1221 static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1222 {
1223         const struct ast_sorcery_object_type_observer *observer = obj;
1224
1225         if (observer->callbacks->loaded) {
1226                 observer->callbacks->loaded(arg);
1227         }
1228
1229         return 0;
1230 }
1231
1232 /*! \brief Internal callback function which notifies observers that an object type has been loaded */
1233 static int sorcery_observers_notify_loaded(void *data)
1234 {
1235         struct sorcery_observer_invocation *invocation = data;
1236
1237         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
1238         ao2_cleanup(invocation);
1239
1240         return 0;
1241 }
1242
1243 static int sorcery_object_load(void *obj, void *arg, int flags)
1244 {
1245         struct ast_sorcery_object_type *type = obj;
1246         struct sorcery_load_details *details = arg;
1247
1248         if (!type->type.item_alloc) {
1249                 return 0;
1250         }
1251
1252         details->type = type->name;
1253
1254         if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
1255                 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, maintaining previous values\n",
1256                         details->type);
1257                 return 0;
1258         }
1259
1260         NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loading,
1261                 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1262
1263         ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
1264
1265         NOTIFY_INSTANCE_OBSERVERS(details->sorcery->observers, object_type_loaded,
1266                 details->sorcery->module_name, details->sorcery, type->name, details->reload);
1267
1268         if (ao2_container_count(type->observers)) {
1269                 struct sorcery_observer_invocation *invocation;
1270
1271                 invocation = sorcery_observer_invocation_alloc(type, NULL);
1272                 if (invocation
1273                         && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded,
1274                                 invocation)) {
1275                         ao2_cleanup(invocation);
1276                 }
1277         }
1278
1279         return 0;
1280 }
1281
1282 void ast_sorcery_load(const struct ast_sorcery *sorcery)
1283 {
1284         struct sorcery_load_details details = {
1285                 .sorcery = sorcery,
1286                 .reload = 0,
1287         };
1288
1289         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1290                 sorcery->module_name, sorcery, 0);
1291
1292         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1293
1294         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
1295                 sorcery->module_name, sorcery, 0);
1296 }
1297
1298 void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1299 {
1300         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1301         struct sorcery_load_details details = {
1302                 .sorcery = sorcery,
1303                 .reload = 0,
1304         };
1305
1306         if (!object_type) {
1307                 return;
1308         }
1309
1310         sorcery_object_load(object_type, &details, 0);
1311 }
1312
1313 void ast_sorcery_reload(const struct ast_sorcery *sorcery)
1314 {
1315         struct sorcery_load_details details = {
1316                 .sorcery = sorcery,
1317                 .reload = 1,
1318         };
1319
1320         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loading,
1321                 sorcery->module_name, sorcery, 1);
1322
1323         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1324
1325         NOTIFY_INSTANCE_OBSERVERS(sorcery->observers, instance_loaded,
1326                 sorcery->module_name, sorcery, 1);
1327
1328 }
1329
1330 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1331 {
1332         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1333         struct sorcery_load_details details = {
1334                 .sorcery = sorcery,
1335                 .reload = 1,
1336         };
1337
1338         if (!object_type) {
1339                 return;
1340         }
1341
1342         sorcery_object_load(object_type, &details, 0);
1343 }
1344
1345 void ast_sorcery_ref(struct ast_sorcery *sorcery)
1346 {
1347         ao2_ref(sorcery, +1);
1348 }
1349
1350 static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1351 {
1352         struct ast_variable *tmp = NULL;
1353         char *buf = NULL;
1354
1355         if (!object_field->handler) {
1356                 return NULL;
1357         }
1358
1359         if (!(object_field->handler(object, object_field->args, &buf))) {
1360                 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1361         }
1362         ast_free(buf);
1363
1364         return tmp;
1365 }
1366
1367 static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1368 {
1369         struct ast_variable *tmp = NULL;
1370
1371         if (!object_field->multiple_handler) {
1372                 return NULL;
1373         }
1374
1375         if (object_field->multiple_handler(object, &tmp)) {
1376                 ast_variables_destroy(tmp);
1377                 tmp = NULL;
1378         }
1379
1380         return tmp;
1381 }
1382
1383 struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
1384         const void *object,     enum ast_sorcery_field_handler_flags flags)
1385 {
1386         const struct ast_sorcery_object_details *details = object;
1387         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1388         struct ao2_iterator i;
1389         struct ast_sorcery_object_field *object_field;
1390         struct ast_variable *head = NULL;
1391         struct ast_variable *tail = NULL;
1392
1393         if (!object_type) {
1394                 return NULL;
1395         }
1396
1397         i = ao2_iterator_init(object_type->fields, 0);
1398
1399         for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1400                 struct ast_variable *tmp;
1401
1402                 switch (flags) {
1403                 case AST_HANDLER_PREFER_LIST:
1404                         if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1405                                 (tmp = get_single_field_as_var_list(object, object_field))) {
1406                                 break;
1407                         }
1408                         continue;
1409                 case AST_HANDLER_PREFER_STRING:
1410                         if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1411                                 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1412                                 break;
1413                         }
1414                         continue;
1415                 case AST_HANDLER_ONLY_LIST:
1416                         if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1417                                 break;
1418                         }
1419                         continue;
1420                 case AST_HANDLER_ONLY_STRING:
1421                         if ((tmp = get_single_field_as_var_list(object, object_field))) {
1422                                 break;
1423                         }
1424                         continue;
1425                 default:
1426                         continue;
1427                 }
1428
1429                 tail = ast_variable_list_append_hint(&head, tail, tmp);
1430         }
1431
1432         ao2_iterator_destroy(&i);
1433
1434         return head;
1435 }
1436
1437 struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1438 {
1439         const struct ast_sorcery_object_details *details = object;
1440         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1441         struct ao2_iterator i;
1442         struct ast_sorcery_object_field *object_field;
1443         struct ast_json *json = ast_json_object_create();
1444         int res = 0;
1445
1446         if (!object_type || !json) {
1447                 return NULL;
1448         }
1449
1450         i = ao2_iterator_init(object_type->fields, 0);
1451
1452         for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1453                 if (object_field->multiple_handler) {
1454                         struct ast_variable *tmp = NULL;
1455                         struct ast_variable *field;
1456
1457                         if ((res = object_field->multiple_handler(object, &tmp))) {
1458                                 ast_variables_destroy(tmp);
1459                                 ao2_ref(object_field, -1);
1460                                 break;
1461                         }
1462
1463                         for (field = tmp; field; field = field->next) {
1464                                 struct ast_json *value = ast_json_string_create(field->value);
1465
1466                                 if (!value || ast_json_object_set(json, field->name, value)) {
1467                                         res = -1;
1468                                         break;
1469                                 }
1470                         }
1471
1472                         ast_variables_destroy(tmp);
1473                 } else if (object_field->handler) {
1474                         char *buf = NULL;
1475                         struct ast_json *value = NULL;
1476
1477                         if ((res = object_field->handler(object, object_field->args, &buf))
1478                                 || !(value = ast_json_string_create(buf))
1479                                 || ast_json_object_set(json, object_field->name, value)) {
1480                                 res = -1;
1481                         }
1482
1483                         ast_free(buf);
1484                 } else {
1485                         continue;
1486                 }
1487         }
1488
1489         ao2_iterator_destroy(&i);
1490
1491         /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1492         if (res) {
1493                 ast_json_unref(json);
1494                 json = NULL;
1495         }
1496
1497         return json;
1498 }
1499
1500 int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1501 {
1502         const struct ast_sorcery_object_details *details = object;
1503         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1504         RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1505         struct ast_variable *field;
1506         int res = 0;
1507
1508         if (!object_type) {
1509                 return -1;
1510         }
1511
1512         if (object_type->transform && (transformed = object_type->transform(objectset))) {
1513                 field = transformed;
1514         } else {
1515                 field = objectset;
1516         }
1517
1518         for (; field; field = field->next) {
1519                 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1520                         break;
1521                 }
1522         }
1523
1524         if (!res && object_type->apply) {
1525                 res = object_type->apply(sorcery, object);
1526         }
1527
1528         return res;
1529 }
1530
1531 int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1532 {
1533         const struct ast_variable *field;
1534         int res = 0;
1535
1536         *changes = NULL;
1537
1538         /* Unless the ast_variable list changes when examined... it can't differ from itself */
1539         if (original == modified) {
1540                 return 0;
1541         }
1542
1543         for (field = modified; field; field = field->next) {
1544                 const char *old_value = ast_variable_find_in_list(original, field->name);
1545
1546                 if (!old_value || strcmp(old_value, field->value)) {
1547                         struct ast_variable *tmp;
1548
1549                         if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1550                                 res = -1;
1551                                 break;
1552                         }
1553
1554                         tmp->next = *changes;
1555                         *changes = tmp;
1556                 }
1557         }
1558
1559         /* If an error occurred do not return a partial changeset */
1560         if (res) {
1561                 ast_variables_destroy(*changes);
1562                 *changes = NULL;
1563         }
1564
1565         return res;
1566 }
1567
1568 static void sorcery_object_destructor(void *object)
1569 {
1570         struct ast_sorcery_object_details *details = object;
1571
1572         if (details->object->destructor) {
1573                 details->object->destructor(object);
1574         }
1575
1576         ast_variables_destroy(details->object->extended);
1577         ast_free(details->object->id);
1578 }
1579
1580 void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1581 {
1582         void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
1583         struct ast_sorcery_object_details *details = object;
1584
1585         if (!object) {
1586                 return NULL;
1587         }
1588
1589         details->object = object + size;
1590         details->object->destructor = destructor;
1591
1592         return object;
1593 }
1594
1595 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1596 {
1597         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1598         struct ast_sorcery_object_details *details;
1599
1600         if (!object_type || !object_type->type.item_alloc ||
1601                 !(details = object_type->type.item_alloc(id))) {
1602                 return NULL;
1603         }
1604
1605         if (ast_strlen_zero(id)) {
1606                 char uuid[AST_UUID_STR_LEN];
1607
1608                 ast_uuid_generate_str(uuid, sizeof(uuid));
1609                 details->object->id = ast_strdup(uuid);
1610         } else {
1611                 details->object->id = ast_strdup(id);
1612         }
1613
1614         ast_copy_string(details->object->type, type, sizeof(details->object->type));
1615
1616         if (aco_set_defaults(&object_type->type, id, details)) {
1617                 ao2_ref(details, -1);
1618                 return NULL;
1619         }
1620
1621         return details;
1622 }
1623
1624 void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1625 {
1626         const struct ast_sorcery_object_details *details = object;
1627         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1628         struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
1629         RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1630         int res = 0;
1631
1632         if (!copy) {
1633                 return NULL;
1634         } else if (object_type->copy) {
1635                 res = object_type->copy(object, copy);
1636         } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1637                 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1638         } else {
1639                 /* No native copy available and could not create an objectset, this copy has failed */
1640                 res = -1;
1641         }
1642
1643         if (res) {
1644                 ao2_cleanup(copy);
1645                 copy = NULL;
1646         }
1647
1648         return copy;
1649 }
1650
1651 int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1652 {
1653         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
1654
1655         *changes = NULL;
1656
1657         if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1658                 return -1;
1659         }
1660
1661         if (original == modified) {
1662                 return 0;
1663         } else if (!object_type->diff) {
1664                 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1665                 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1666
1667                 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1668                 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1669
1670                 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1671         } else {
1672                 return object_type->diff(original, modified, changes);
1673         }
1674 }
1675
1676 /*! \brief Structure used when calling create, update, or delete */
1677 struct sorcery_details {
1678         /*! \brief Pointer to the sorcery instance */
1679         const struct ast_sorcery *sorcery;
1680         /*! \brief Pointer to the object itself */
1681         void *obj;
1682 };
1683
1684 /*! \brief Internal function used to create an object in caching wizards */
1685 static int sorcery_cache_create(void *obj, void *arg, int flags)
1686 {
1687         const struct ast_sorcery_object_wizard *object_wizard = obj;
1688         const struct sorcery_details *details = arg;
1689
1690         if (!object_wizard->caching || !object_wizard->wizard->callbacks.create) {
1691                 return 0;
1692         }
1693
1694         object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj);
1695
1696         return 0;
1697 }
1698
1699 void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1700 {
1701         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1702         void *object = NULL;
1703         struct ao2_iterator i;
1704         struct ast_sorcery_object_wizard *wizard;
1705         unsigned int cached = 0;
1706
1707         if (!object_type || ast_strlen_zero(id)) {
1708                 return NULL;
1709         }
1710
1711         i = ao2_iterator_init(object_type->wizards, 0);
1712         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1713                 if (wizard->wizard->callbacks.retrieve_id &&
1714                         !(object = wizard->wizard->callbacks.retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1715                         continue;
1716                 }
1717
1718                 cached = wizard->caching;
1719
1720                 ao2_ref(wizard, -1);
1721                 break;
1722         }
1723         ao2_iterator_destroy(&i);
1724
1725         if (!cached && object) {
1726                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1727         }
1728
1729         return object;
1730 }
1731
1732 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1733 {
1734         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1735         void *object = NULL;
1736         struct ao2_iterator i;
1737         struct ast_sorcery_object_wizard *wizard;
1738         unsigned int cached = 0;
1739
1740         if (!object_type) {
1741                 return NULL;
1742         }
1743
1744         /* If returning multiple objects create a container to store them in */
1745         if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1746                 if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1747                         return NULL;
1748                 }
1749         }
1750
1751         /* Inquire with the available wizards for retrieval */
1752         i = ao2_iterator_init(object_type->wizards, 0);
1753         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1754                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1755                         if (wizard->wizard->callbacks.retrieve_multiple) {
1756                                 wizard->wizard->callbacks.retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1757                         }
1758                 } else if (fields && wizard->wizard->callbacks.retrieve_fields) {
1759                         if (wizard->wizard->callbacks.retrieve_fields) {
1760                                 object = wizard->wizard->callbacks.retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1761                         }
1762                 }
1763
1764                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
1765                         continue;
1766                 }
1767
1768                 cached = wizard->caching;
1769
1770                 ao2_ref(wizard, -1);
1771                 break;
1772         }
1773         ao2_iterator_destroy(&i);
1774
1775         /* If we are returning a single object and it came from a non-cache source create it in any caches */
1776         if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1777                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1778         }
1779
1780         return object;
1781 }
1782
1783 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1784 {
1785         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1786         struct ao2_container *objects;
1787         struct ao2_iterator i;
1788         struct ast_sorcery_object_wizard *wizard;
1789
1790         if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1791                 return NULL;
1792         }
1793
1794         i = ao2_iterator_init(object_type->wizards, 0);
1795         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1796                 if (!wizard->wizard->callbacks.retrieve_regex) {
1797                         continue;
1798                 }
1799
1800                 wizard->wizard->callbacks.retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1801         }
1802         ao2_iterator_destroy(&i);
1803
1804         return objects;
1805 }
1806
1807 /*! \brief Internal function which returns if the wizard has created the object */
1808 static int sorcery_wizard_create(void *obj, void *arg, int flags)
1809 {
1810         const struct ast_sorcery_object_wizard *object_wizard = obj;
1811         const struct sorcery_details *details = arg;
1812
1813         if (!object_wizard->wizard->callbacks.create) {
1814                 ast_assert(0);
1815                 ast_log(LOG_ERROR, "Sorcery wizard '%s' doesn't contain a 'create' virtual function.\n",
1816                         object_wizard->wizard->callbacks.name);
1817                 return 0;
1818         }
1819         return (!object_wizard->caching && !object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
1820 }
1821
1822 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
1823 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
1824 {
1825         const struct ast_sorcery_object_type_observer *observer = obj;
1826
1827         if (observer->callbacks->created) {
1828                 observer->callbacks->created(arg);
1829         }
1830
1831         return 0;
1832 }
1833
1834 /*! \brief Internal callback function which notifies observers that an object has been created */
1835 static int sorcery_observers_notify_create(void *data)
1836 {
1837         struct sorcery_observer_invocation *invocation = data;
1838
1839         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
1840         ao2_cleanup(invocation);
1841
1842         return 0;
1843 }
1844
1845 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
1846 {
1847         const struct ast_sorcery_object_details *details = object;
1848         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1849         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1850         struct sorcery_details sdetails = {
1851                 .sorcery = sorcery,
1852                 .obj = object,
1853         };
1854
1855         if (!object_type) {
1856                 return -1;
1857         }
1858
1859         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
1860                 ao2_container_count(object_type->observers)) {
1861                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1862
1863                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
1864                         ao2_cleanup(invocation);
1865                 }
1866         }
1867
1868         return object_wizard ? 0 : -1;
1869 }
1870
1871 /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
1872 static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
1873 {
1874         const struct ast_sorcery_object_type_observer *observer = obj;
1875
1876         if (observer->callbacks->updated) {
1877                 observer->callbacks->updated(arg);
1878         }
1879
1880         return 0;
1881 }
1882
1883 /*! \brief Internal callback function which notifies observers that an object has been updated */
1884 static int sorcery_observers_notify_update(void *data)
1885 {
1886         struct sorcery_observer_invocation *invocation = data;
1887
1888         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
1889         ao2_cleanup(invocation);
1890
1891         return 0;
1892 }
1893
1894 /*! \brief Internal function which returns if a wizard has updated the object */
1895 static int sorcery_wizard_update(void *obj, void *arg, int flags)
1896 {
1897         const struct ast_sorcery_object_wizard *object_wizard = obj;
1898         const struct sorcery_details *details = arg;
1899
1900         return (object_wizard->wizard->callbacks.update && !object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj) &&
1901                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1902 }
1903
1904 int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
1905 {
1906         const struct ast_sorcery_object_details *details = object;
1907         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1908         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1909         struct sorcery_details sdetails = {
1910                 .sorcery = sorcery,
1911                 .obj = object,
1912         };
1913
1914         if (!object_type) {
1915                 return -1;
1916         }
1917
1918         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
1919                 ao2_container_count(object_type->observers)) {
1920                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1921
1922                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
1923                         ao2_cleanup(invocation);
1924                 }
1925         }
1926
1927         return object_wizard ? 0 : -1;
1928 }
1929
1930 /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
1931 static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
1932 {
1933         const struct ast_sorcery_object_type_observer *observer = obj;
1934
1935         if (observer->callbacks->deleted) {
1936                 observer->callbacks->deleted(arg);
1937         }
1938
1939         return 0;
1940 }
1941
1942 /*! \brief Internal callback function which notifies observers that an object has been deleted */
1943 static int sorcery_observers_notify_delete(void *data)
1944 {
1945         struct sorcery_observer_invocation *invocation = data;
1946
1947         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
1948         ao2_cleanup(invocation);
1949
1950         return 0;
1951 }
1952
1953 /*! \brief Internal function which returns if a wizard has deleted the object */
1954 static int sorcery_wizard_delete(void *obj, void *arg, int flags)
1955 {
1956         const struct ast_sorcery_object_wizard *object_wizard = obj;
1957         const struct sorcery_details *details = arg;
1958
1959         return (object_wizard->wizard->callbacks.delete && !object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj) &&
1960                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1961 }
1962
1963 int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
1964 {
1965         const struct ast_sorcery_object_details *details = object;
1966         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1967         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1968         struct sorcery_details sdetails = {
1969                 .sorcery = sorcery,
1970                 .obj = object,
1971         };
1972
1973         if (!object_type) {
1974                 return -1;
1975         }
1976
1977         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
1978                 ao2_container_count(object_type->observers)) {
1979                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1980
1981                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
1982                         ao2_cleanup(invocation);
1983                 }
1984         }
1985
1986         return object_wizard ? 0 : -1;
1987 }
1988
1989 void ast_sorcery_unref(struct ast_sorcery *sorcery)
1990 {
1991         if (sorcery) {
1992                 /* One ref for what we just released, the other for the instances container. */
1993                 ao2_wrlock(instances);
1994                 if (ao2_ref(sorcery, -1) == 2) {
1995                         ao2_unlink_flags(instances, sorcery, OBJ_NOLOCK);
1996                 }
1997                 ao2_unlock(instances);
1998         }
1999 }
2000
2001 const char *ast_sorcery_object_get_id(const void *object)
2002 {
2003         const struct ast_sorcery_object_details *details = object;
2004         return details->object->id;
2005 }
2006
2007 const char *ast_sorcery_object_get_type(const void *object)
2008 {
2009         const struct ast_sorcery_object_details *details = object;
2010         return details->object->type;
2011 }
2012
2013 const char *ast_sorcery_object_get_extended(const void *object, const char *name)
2014 {
2015         const struct ast_sorcery_object_details *details = object;
2016         struct ast_variable *field;
2017
2018         for (field = details->object->extended; field; field = field->next) {
2019                 if (!strcmp(field->name + 1, name)) {
2020                         return field->value;
2021                 }
2022         }
2023
2024         return NULL;
2025 }
2026
2027 int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
2028 {
2029         RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
2030         struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
2031         const struct ast_sorcery_object_details *details = object;
2032
2033         if (!extended) {
2034                 return -1;
2035         }
2036
2037         for (field = details->object->extended; field; previous = field, field = field->next) {
2038                 if (!strcmp(field->name, name)) {
2039                         if (previous) {
2040                                 previous->next = field->next;
2041                         } else {
2042                                 details->object->extended = field->next;
2043                         }
2044                         field->next = NULL;
2045                         break;
2046                 }
2047         }
2048
2049         extended->next = details->object->extended;
2050         details->object->extended = extended;
2051
2052         return 0;
2053 }
2054
2055 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
2056 {
2057         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
2058         struct ast_sorcery_object_type_observer *observer;
2059         int res;
2060
2061         if (!object_type || !callbacks) {
2062                 return -1;
2063         }
2064
2065         if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
2066                 return -1;
2067         }
2068
2069         observer->callbacks = callbacks;
2070         res = 0;
2071         if (!ao2_link(object_type->observers, observer)) {
2072                 res = -1;
2073         }
2074         ao2_ref(observer, -1);
2075
2076         return res;
2077 }
2078
2079 /*! \brief Internal callback function for removing an observer */
2080 static int sorcery_observer_remove(void *obj, void *arg, int flags)
2081 {
2082         const struct ast_sorcery_object_type_observer *observer = obj;
2083
2084         return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
2085 }
2086
2087 void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
2088 {
2089         RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
2090         struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
2091
2092         if (!sorcery) {
2093                 return;
2094         }
2095         object_type = ao2_find(sorcery->types, type, OBJ_KEY);
2096         if (!object_type) {
2097                 return;
2098         }
2099
2100         ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
2101                 sorcery_observer_remove, cbs);
2102 }
2103
2104 int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
2105 {
2106         const char *right_key = arg;
2107         int cmp;
2108
2109         switch (flags & OBJ_SEARCH_MASK) {
2110         case OBJ_SEARCH_OBJECT:
2111                 right_key = ast_sorcery_object_get_id(arg);
2112                 /* Fall through */
2113         case OBJ_SEARCH_KEY:
2114                 cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
2115                 break;
2116         case OBJ_SEARCH_PARTIAL_KEY:
2117                 cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
2118                 break;
2119         default:
2120                 cmp = 0;
2121                 break;
2122         }
2123         return cmp;
2124 }
2125
2126 int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
2127 {
2128         const char *right_key = arg;
2129         int cmp = 0;
2130
2131         switch (flags & OBJ_SEARCH_MASK) {
2132         case OBJ_SEARCH_OBJECT:
2133                 right_key = ast_sorcery_object_get_id(arg);
2134                 /* Fall through */
2135         case OBJ_SEARCH_KEY:
2136                 if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
2137                         cmp = CMP_MATCH | CMP_STOP;
2138                 }
2139                 break;
2140         case OBJ_SEARCH_PARTIAL_KEY:
2141                 if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
2142                         cmp = CMP_MATCH;
2143                 }
2144                 break;
2145         default:
2146                 cmp = 0;
2147                 break;
2148         }
2149         return cmp;
2150 }
2151
2152 int ast_sorcery_object_id_hash(const void *obj, int flags) {
2153         if (flags & OBJ_SEARCH_OBJECT) {
2154                 return ast_str_hash(ast_sorcery_object_get_id(obj));
2155         } else if (flags & OBJ_SEARCH_KEY) {
2156                 return ast_str_hash(obj);
2157         }
2158         return -1;
2159 }
2160
2161 struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
2162                 const char *type)
2163 {
2164         return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
2165 }
2166
2167 static int is_registered_cb(void *obj, void *arg, int flags)
2168 {
2169         struct ast_sorcery_object_field *object_field = obj;
2170         char *name = arg;
2171         int rc = 0;
2172
2173         if (object_field->name_regex
2174                 && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
2175                 rc = CMP_MATCH | CMP_STOP;
2176         }
2177
2178         return rc;
2179 }
2180
2181 int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
2182                 const char *field_name)
2183 {
2184         struct ast_sorcery_object_field *object_field;
2185         int res = 1;
2186
2187         ast_assert(object_type != NULL);
2188
2189         object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
2190
2191         if (!object_field) {
2192                 object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
2193         }
2194
2195         if (!object_field) {
2196                 res = 0;
2197         }
2198
2199         ao2_cleanup(object_field);
2200         return res;
2201 }