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