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