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