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