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