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