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