func_pjsip_endpoint: Add PJSIP_ENDPOINT function for querying endpoint details
[asterisk/asterisk.git] / main / sorcery.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Sorcery Data Access Layer API
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/logger.h"
35 #include "asterisk/sorcery.h"
36 #include "asterisk/astobj2.h"
37 #include "asterisk/format.h"
38 #include "asterisk/format_cap.h"
39 #include "asterisk/strings.h"
40 #include "asterisk/config_options.h"
41 #include "asterisk/netsock2.h"
42 #include "asterisk/module.h"
43 #include "asterisk/taskprocessor.h"
44 #include "asterisk/threadpool.h"
45 #include "asterisk/json.h"
46
47 /* To prevent DEBUG_FD_LEAKS from interfering with things we undef open and close */
48 #undef open
49 #undef close
50
51 /*! \brief Number of buckets for wizards (should be prime for performance reasons) */
52 #define WIZARD_BUCKETS 7
53
54 /*! \brief Number of buckets for types (should be prime for performance reasons) */
55 #define TYPE_BUCKETS 53
56
57 /*! \brief Thread pool for observers */
58 static struct ast_threadpool *threadpool;
59
60 /*! \brief Structure for internal sorcery object information */
61 struct ast_sorcery_object {
62         /*! \brief Unique identifier of this object */
63         char *id;
64
65         /*! \brief Type of object */
66         char type[MAX_OBJECT_TYPE];
67
68         /*! \brief Optional object destructor */
69         ao2_destructor_fn destructor;
70
71         /*! \brief Extended object fields */
72         struct ast_variable *extended;
73 };
74
75 /*! \brief Structure for registered object type */
76 struct ast_sorcery_object_type {
77         /*! \brief Unique name of the object type */
78         char name[MAX_OBJECT_TYPE];
79
80         /*! \brief Optional transformation callback */
81         sorcery_transform_handler transform;
82
83         /*! \brief Optional object set apply callback */
84         sorcery_apply_handler apply;
85
86         /*! \brief Optional object copy callback */
87         sorcery_copy_handler copy;
88
89         /*! \brief Optional object diff callback */
90         sorcery_diff_handler diff;
91
92         /*! \brief Wizard instances */
93         struct ao2_container *wizards;
94
95         /*! \brief Object fields */
96         struct ao2_container *fields;
97
98         /*! \brief Configuration framework general information */
99         struct aco_info *info;
100
101         /*! \brief Configuration framework file information */
102         struct aco_file *file;
103
104         /*! \brief Type details */
105         struct aco_type type;
106
107         /*! \brief Observers */
108         struct ao2_container *observers;
109
110         /*! \brief Serializer for observers */
111         struct ast_taskprocessor *serializer;
112
113         /*! \brief Specifies if object type is reloadable or not */
114         unsigned int reloadable:1;
115 };
116
117 /*! \brief Structure for registered object type observer */
118 struct ast_sorcery_object_type_observer {
119         /*! \brief Pointer to the observer implementation */
120         const struct ast_sorcery_observer *callbacks;
121 };
122
123 /*! \brief Structure used for observer invocations */
124 struct sorcery_observer_invocation {
125         /*! \brief Pointer to the object type */
126         struct ast_sorcery_object_type *object_type;
127
128         /*! \brief Pointer to the object */
129         void *object;
130 };
131
132 /*! \brief Structure for registered object field */
133 struct ast_sorcery_object_field {
134         /*! \brief Name of the field */
135         char name[MAX_OBJECT_FIELD];
136
137         /*! \brief Callback function for translation of a single value */
138         sorcery_field_handler handler;
139
140         /*! \brief Callback function for translation of multiple values */
141         sorcery_fields_handler multiple_handler;
142
143         /*! \brief Position of the field */
144         intptr_t args[];
145 };
146
147 /*! \brief Structure for a wizard instance which operates on objects */
148 struct ast_sorcery_object_wizard {
149         /*! \brief Wizard interface itself */
150         struct ast_sorcery_wizard *wizard;
151
152         /*! \brief Unique data for the wizard */
153         void *data;
154
155         /*! \brief Wizard is acting as an object cache */
156         unsigned int caching:1;
157 };
158
159 /*! \brief Full structure for sorcery */
160 struct ast_sorcery {
161         /*! \brief Container for known object types */
162         struct ao2_container *types;
163 };
164
165 /*! \brief Structure for passing load/reload details */
166 struct sorcery_load_details {
167         /*! \brief Sorcery structure in use */
168         const struct ast_sorcery *sorcery;
169
170         /*! \brief Type of object being loaded */
171         const char *type;
172
173         /*! \brief Whether this is a reload or not */
174         unsigned int reload:1;
175 };
176
177 /*! \brief Registered sorcery wizards */
178 struct ao2_container *wizards;
179
180 static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
181 {
182         int *field = (int *)(obj + args[0]);
183         return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
184 }
185
186 static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
187 {
188         unsigned int *field = (unsigned int *)(obj + args[0]);
189         return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
190 }
191
192 static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
193 {
194         double *field = (double *)(obj + args[0]);
195         return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
196 }
197
198 static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
199 {
200         ast_string_field *field = (const char **)(obj + args[0]);
201         return !(*buf = ast_strdup(*field)) ? -1 : 0;
202 }
203
204 static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
205 {
206         unsigned int *field = (unsigned int *)(obj + args[0]);
207         return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
208 }
209
210 static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
211 {
212         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
213         return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
214 }
215
216 static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
217 {
218         char *field = (char *)(obj + args[0]);
219         return !(*buf = ast_strdup(field)) ? -1 : 0;
220 }
221
222 static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
223 {
224         char tmp_buf[256];
225         struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[1]);
226         return !(*buf = ast_strdup(ast_getformatname_multiple(tmp_buf, sizeof(tmp_buf), *cap)));
227 }
228
229 static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
230 {
231         switch(type) {
232         case OPT_BOOL_T: return bool_handler_fn;
233         case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
234         case OPT_CODEC_T: return codec_handler_fn;
235         case OPT_DOUBLE_T: return double_handler_fn;
236         case OPT_INT_T: return int_handler_fn;
237         case OPT_SOCKADDR_T: return sockaddr_handler_fn;
238         case OPT_STRINGFIELD_T: return stringfield_handler_fn;
239         case OPT_UINT_T: return uint_handler_fn;
240
241         default:
242         case OPT_CUSTOM_T: return NULL;
243         }
244
245         return NULL;
246 }
247
248 /*! \brief Hashing function for sorcery wizards */
249 static int sorcery_wizard_hash(const void *obj, const int flags)
250 {
251         const struct ast_sorcery_wizard *wizard = obj;
252         const char *name = obj;
253
254         return ast_str_hash(flags & OBJ_KEY ? name : wizard->name);
255 }
256
257 /*! \brief Comparator function for sorcery wizards */
258 static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
259 {
260         struct ast_sorcery_wizard *wizard1 = obj, *wizard2 = arg;
261         const char *name = arg;
262
263         return !strcmp(wizard1->name, flags & OBJ_KEY ? name : wizard2->name) ? CMP_MATCH | CMP_STOP : 0;
264 }
265
266 /*! \brief Cleanup function */
267 static void sorcery_exit(void)
268 {
269         ast_threadpool_shutdown(threadpool);
270         threadpool = NULL;
271 }
272
273 /*! \brief Cleanup function for graceful shutdowns */
274 static void sorcery_cleanup(void)
275 {
276         ao2_cleanup(wizards);
277 }
278
279 int ast_sorcery_init(void)
280 {
281         struct ast_threadpool_options options = {
282                 .version = AST_THREADPOOL_OPTIONS_VERSION,
283                 .auto_increment = 1,
284                 .max_size = 0,
285                 .idle_timeout = 60,
286                 .initial_size = 0,
287         };
288         ast_assert(wizards == NULL);
289
290         if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
291                 threadpool = NULL;
292                 return -1;
293         }
294
295         if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
296                 ast_threadpool_shutdown(threadpool);
297                 return -1;
298         }
299
300         ast_register_cleanup(sorcery_cleanup);
301         ast_register_atexit(sorcery_exit);
302
303         return 0;
304 }
305
306 int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
307 {
308         struct ast_sorcery_wizard *wizard;
309         int res = -1;
310
311         ast_assert(!ast_strlen_zero(interface->name));
312
313         ao2_lock(wizards);
314
315         if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
316                 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
317                         interface->name);
318                 goto done;
319         }
320
321         if (!(wizard = ao2_alloc(sizeof(*wizard), NULL))) {
322                 goto done;
323         }
324
325         *wizard = *interface;
326         wizard->module = module;
327
328         ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
329         res = 0;
330
331         ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
332
333 done:
334         ao2_cleanup(wizard);
335         ao2_unlock(wizards);
336
337         return res;
338 }
339
340 int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
341 {
342         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, interface->name, OBJ_KEY | OBJ_UNLINK), ao2_cleanup);
343
344         if (wizard) {
345                 ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
346                 return 0;
347         } else {
348                 return -1;
349         }
350 }
351
352 /*! \brief Destructor called when sorcery structure is destroyed */
353 static void sorcery_destructor(void *obj)
354 {
355         struct ast_sorcery *sorcery = obj;
356
357         ao2_cleanup(sorcery->types);
358 }
359
360 /*! \brief Hashing function for sorcery types */
361 static int sorcery_type_hash(const void *obj, const int flags)
362 {
363         const struct ast_sorcery_object_type *type = obj;
364         const char *name = obj;
365
366         return ast_str_hash(flags & OBJ_KEY ? name : type->name);
367 }
368
369 /*! \brief Comparator function for sorcery types */
370 static int sorcery_type_cmp(void *obj, void *arg, int flags)
371 {
372         struct ast_sorcery_object_type *type1 = obj, *type2 = arg;
373         const char *name = arg;
374
375         return !strcmp(type1->name, flags & OBJ_KEY ? name : type2->name) ? CMP_MATCH | CMP_STOP : 0;
376 }
377
378 struct ast_sorcery *ast_sorcery_open(void)
379 {
380         struct ast_sorcery *sorcery;
381
382         if (!(sorcery = ao2_alloc(sizeof(*sorcery), sorcery_destructor))) {
383                 return NULL;
384         }
385
386         if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
387                 ao2_ref(sorcery, -1);
388                 sorcery = NULL;
389         }
390
391         return sorcery;
392 }
393
394 /*! \brief Destructor function for object types */
395 static void sorcery_object_type_destructor(void *obj)
396 {
397         struct ast_sorcery_object_type *object_type = obj;
398
399         ao2_cleanup(object_type->wizards);
400         ao2_cleanup(object_type->fields);
401         ao2_cleanup(object_type->observers);
402
403         if (object_type->info) {
404                 aco_info_destroy(object_type->info);
405                 ast_free(object_type->info);
406         }
407
408         ast_free(object_type->file);
409
410         ast_taskprocessor_unreference(object_type->serializer);
411 }
412
413 /*! \brief Internal function which allocates an object type structure */
414 static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
415 {
416         struct ast_sorcery_object_type *object_type;
417         char uuid[AST_UUID_STR_LEN];
418
419         if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
420                 return NULL;
421         }
422
423         /* Order matters for object wizards */
424         if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
425                 ao2_ref(object_type, -1);
426                 return NULL;
427         }
428
429         if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
430                 ao2_ref(object_type, -1);
431                 return NULL;
432         }
433
434         if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
435                 ao2_ref(object_type, -1);
436                 return NULL;
437         }
438
439         if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
440                 ao2_ref(object_type, -1);
441                 return NULL;
442         }
443
444         if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
445                 ao2_ref(object_type, -1);
446                 return NULL;
447         }
448
449         if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
450                 ao2_ref(object_type, -1);
451                 return NULL;
452         }
453
454         if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
455                 ao2_ref(object_type, -1);
456                 return NULL;
457         }
458
459         object_type->info->files[0] = object_type->file;
460         object_type->info->files[1] = NULL;
461         object_type->info->module = module;
462
463         ast_copy_string(object_type->name, type, sizeof(object_type->name));
464
465         return object_type;
466 }
467
468 /*! \brief Object wizard destructor */
469 static void sorcery_object_wizard_destructor(void *obj)
470 {
471         struct ast_sorcery_object_wizard *object_wizard = obj;
472
473         if (object_wizard->data) {
474                 object_wizard->wizard->close(object_wizard->data);
475         }
476
477         if (object_wizard->wizard) {
478                 ast_module_unref(object_wizard->wizard->module);
479         }
480 }
481
482 /*! \brief Internal function which creates an object type and adds a wizard mapping */
483 static int sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data, unsigned int caching)
484 {
485         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
486         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
487         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
488         int created = 0;
489
490         if (!wizard || !object_wizard) {
491                 return -1;
492         }
493
494         if (!object_type) {
495                 if (!(object_type = sorcery_object_type_alloc(type, module))) {
496                         return -1;
497                 }
498                 created = 1;
499         }
500
501         if (wizard->open && !(object_wizard->data = wizard->open(data))) {
502                 return -1;
503         }
504
505         ast_module_ref(wizard->module);
506
507         object_wizard->wizard = wizard;
508         object_wizard->caching = caching;
509
510         ao2_link(object_type->wizards, object_wizard);
511
512         if (created) {
513                 ao2_link(sorcery->types, object_type);
514         }
515
516         return 0;
517 }
518
519 int __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
520 {
521         struct ast_flags flags = { 0 };
522         struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
523         struct ast_variable *mapping;
524         int res = 0;
525
526         if (!config || config == CONFIG_STATUS_FILEINVALID) {
527                 return -1;
528         }
529
530         for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
531                 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
532                 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
533                 char *options = mapping_name;
534                 char *type = strsep(&options, "/");
535                 char *data = mapping_value;
536                 char *wizard = strsep(&data, ",");
537                 unsigned int caching = 0;
538
539                 /* If no object type or wizard exists just skip, nothing we can do */
540                 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
541                         continue;
542                 }
543
544                 /* If the wizard is configured as a cache treat it as such */
545                 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
546                         caching = 1;
547                 }
548
549                 /* Any error immediately causes us to stop */
550                 if (sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching)) {
551                         res = -1;
552                         break;
553                 }
554         }
555
556         ast_config_destroy(config);
557
558         return res;
559 }
560
561 int __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, const char *module, const char *name, const char *data)
562 {
563         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
564
565         /* Defaults can not be added if any existing mapping exists */
566         if (object_type) {
567                 return -1;
568         }
569
570         return sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
571 }
572
573 static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
574 {
575         return ast_sorcery_object_set_extended(obj, var->name, var->value);
576 }
577
578 static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
579 {
580         const struct ast_sorcery_object_details *details = obj;
581
582         if (details->object->extended) {
583                 *fields = ast_variables_dup(details->object->extended);
584         } else {
585                 *fields = NULL;
586         }
587
588         return 0;
589 }
590
591 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)
592 {
593         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
594
595         if (!object_type || object_type->type.item_alloc) {
596                 return -1;
597         }
598
599         object_type->type.name = object_type->name;
600         object_type->type.type = ACO_ITEM;
601         object_type->type.category = ".?";
602         object_type->type.item_alloc = alloc;
603         object_type->type.hidden = hidden;
604
605         object_type->reloadable = reloadable;
606         object_type->transform = transform;
607         object_type->apply = apply;
608         object_type->file->types[0] = &object_type->type;
609         object_type->file->types[1] = NULL;
610
611         if (aco_info_init(object_type->info)) {
612                 return -1;
613         }
614
615         if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
616                 return -1;
617         }
618
619         return 0;
620 }
621
622 void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
623 {
624         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
625
626         if (!object_type) {
627                 return;
628         }
629
630         object_type->copy = copy;
631 }
632
633 void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
634 {
635         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
636
637         if (!object_type) {
638                 return;
639         }
640
641         object_type->diff = diff;
642 }
643
644 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)
645 {
646         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
647         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
648
649         if (!object_type || !object_type->type.item_alloc || !config_handler || !(object_field = ao2_alloc(sizeof(*object_field), NULL))) {
650                 return -1;
651         }
652
653         ast_copy_string(object_field->name, regex, sizeof(object_field->name));
654         object_field->multiple_handler = sorcery_handler;
655
656         ao2_link(object_type->fields, object_field);
657         __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
658
659         return 0;
660 }
661
662 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,
663                                         aco_option_handler config_handler, sorcery_field_handler sorcery_handler, unsigned int flags, unsigned int no_doc, size_t argc, ...)
664 {
665         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
666         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
667         int pos;
668         va_list args;
669
670         if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
671                 return -1;
672         }
673
674         if (!sorcery_handler) {
675                 sorcery_handler = sorcery_field_default_handler(opt_type);
676         }
677
678         if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
679                 return -1;
680         }
681
682         ast_copy_string(object_field->name, name, sizeof(object_field->name));
683         object_field->handler = sorcery_handler;
684
685         va_start(args, argc);
686         for (pos = 0; pos < argc; pos++) {
687                 object_field->args[pos] = va_arg(args, size_t);
688         }
689         va_end(args);
690
691         ao2_link(object_type->fields, object_field);
692
693         /* TODO: Improve this hack */
694         if (!argc) {
695                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
696         } else if (argc == 1) {
697                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
698                         object_field->args[0]);
699         } else if (argc == 2) {
700                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
701                         object_field->args[0], object_field->args[1]);
702         } else if (argc == 3) {
703                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
704                         object_field->args[0], object_field->args[1], object_field->args[2]);
705         } else {
706                 ast_assert(0); /* The hack... she does us no good for this */
707         }
708
709         return 0;
710 }
711
712 /*! \brief Retrieves whether or not the type is reloadable */
713 static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
714 {
715         RAII_VAR(struct ast_sorcery_object_type *, object_type,
716                  ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
717         return object_type && object_type->reloadable;
718 }
719
720 static int sorcery_wizard_load(void *obj, void *arg, int flags)
721 {
722         struct ast_sorcery_object_wizard *wizard = obj;
723         struct sorcery_load_details *details = arg;
724         void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
725
726         if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
727                 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, "
728                         "maintaining previous values\n", details->type);
729                 return 0;
730         }
731
732         load = !details->reload ? wizard->wizard->load : wizard->wizard->reload;
733
734         if (load) {
735                 load(wizard->data, details->sorcery, details->type);
736         }
737
738         return 0;
739 }
740
741 /*! \brief Destructor for observer invocation */
742 static void sorcery_observer_invocation_destroy(void *obj)
743 {
744         struct sorcery_observer_invocation *invocation = obj;
745
746         ao2_cleanup(invocation->object_type);
747         ao2_cleanup(invocation->object);
748 }
749
750 /*! \brief Allocator function for observer invocation */
751 static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
752 {
753         struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
754
755         if (!invocation) {
756                 return NULL;
757         }
758
759         ao2_ref(object_type, +1);
760         invocation->object_type = object_type;
761
762         if (object) {
763                 ao2_ref(object, +1);
764                 invocation->object = object;
765         }
766
767         return invocation;
768 }
769
770 /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
771 static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
772 {
773         const struct ast_sorcery_object_type_observer *observer = obj;
774
775         if (observer->callbacks->loaded) {
776                 observer->callbacks->loaded(arg);
777         }
778
779         return 0;
780 }
781
782 /*! \brief Internal callback function which notifies observers that an object type has been loaded */
783 static int sorcery_observers_notify_loaded(void *data)
784 {
785         struct sorcery_observer_invocation *invocation = data;
786
787         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
788         ao2_cleanup(invocation);
789
790         return 0;
791 }
792
793 static int sorcery_object_load(void *obj, void *arg, int flags)
794 {
795         struct ast_sorcery_object_type *type = obj;
796         struct sorcery_load_details *details = arg;
797
798         details->type = type->name;
799         ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
800
801         if (ao2_container_count(type->observers)) {
802                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(type, NULL);
803
804                 if (invocation && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded, invocation)) {
805                         ao2_cleanup(invocation);
806                 }
807         }
808
809         return 0;
810 }
811
812 void ast_sorcery_load(const struct ast_sorcery *sorcery)
813 {
814         struct sorcery_load_details details = {
815                 .sorcery = sorcery,
816                 .reload = 0,
817         };
818
819         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
820 }
821
822 void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
823 {
824         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
825         struct sorcery_load_details details = {
826                 .sorcery = sorcery,
827                 .reload = 0,
828         };
829
830         if (!object_type) {
831                 return;
832         }
833
834         sorcery_object_load(object_type, &details, 0);
835 }
836
837 void ast_sorcery_reload(const struct ast_sorcery *sorcery)
838 {
839         struct sorcery_load_details details = {
840                 .sorcery = sorcery,
841                 .reload = 1,
842         };
843
844         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
845 }
846
847 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
848 {
849         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
850         struct sorcery_load_details details = {
851                 .sorcery = sorcery,
852                 .reload = 1,
853         };
854
855         if (!object_type) {
856                 return;
857         }
858
859         sorcery_object_load(object_type, &details, 0);
860 }
861
862 void ast_sorcery_ref(struct ast_sorcery *sorcery)
863 {
864         ao2_ref(sorcery, +1);
865 }
866
867 struct ast_variable *ast_sorcery_objectset_create(const struct ast_sorcery *sorcery, const void *object)
868 {
869         const struct ast_sorcery_object_details *details = object;
870         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
871         struct ao2_iterator i;
872         struct ast_sorcery_object_field *object_field;
873         struct ast_variable *fields = NULL;
874         int res = 0;
875
876         if (!object_type) {
877                 return NULL;
878         }
879
880         i = ao2_iterator_init(object_type->fields, 0);
881
882         for (; (object_field = ao2_iterator_next(&i)) && !res; ao2_ref(object_field, -1)) {
883                 struct ast_variable *tmp = NULL;
884
885                 if (object_field->multiple_handler) {
886                         if ((res = object_field->multiple_handler(object, &tmp))) {
887                                 ast_variables_destroy(tmp);
888                         }
889                 } else if (object_field->handler) {
890                         char *buf = NULL;
891
892                         if ((res = object_field->handler(object, object_field->args, &buf)) ||
893                                 !(tmp = ast_variable_new(object_field->name, S_OR(buf, ""), ""))) {
894                                 res = -1;
895                         }
896
897                         ast_free(buf);
898                 } else {
899                         continue;
900                 }
901
902                 if (!res && tmp) {
903                         tmp->next = fields;
904                         fields = tmp;
905                 }
906         }
907
908         ao2_iterator_destroy(&i);
909
910         /* If any error occurs we destroy all fields handled before so a partial objectset is not returned */
911         if (res) {
912                 ast_variables_destroy(fields);
913                 fields = NULL;
914         }
915
916         return fields;
917 }
918
919 struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
920 {
921         const struct ast_sorcery_object_details *details = object;
922         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
923         struct ao2_iterator i;
924         struct ast_sorcery_object_field *object_field;
925         struct ast_json *json = ast_json_object_create();
926         int res = 0;
927
928         if (!object_type || !json) {
929                 return NULL;
930         }
931
932         i = ao2_iterator_init(object_type->fields, 0);
933
934         for (; (object_field = ao2_iterator_next(&i)) && !res; ao2_ref(object_field, -1)) {
935                 if (object_field->multiple_handler) {
936                         struct ast_variable *tmp = NULL;
937                         struct ast_variable *field;
938
939                         if ((res = object_field->multiple_handler(object, &tmp))) {
940                                 ao2_ref(object_field, -1);
941                                 break;
942                         }
943
944                         for (field = tmp; field; field = field->next) {
945                                 struct ast_json *value = ast_json_string_create(field->value);
946
947                                 if (value && ast_json_object_set(json, field->name, value)) {
948                                         ast_json_unref(value);
949                                         res = -1;
950                                 }
951                         }
952
953                         ast_variables_destroy(tmp);
954                 } else if (object_field->handler) {
955                         char *buf = NULL;
956                         struct ast_json *value = NULL;
957
958                         if ((res = object_field->handler(object, object_field->args, &buf)) ||
959                                 !(value = ast_json_string_create(buf)) ||
960                                 ast_json_object_set(json, object_field->name, value)) {
961                                 ast_json_unref(value);
962                                 res = -1;
963                         }
964
965                         ast_free(buf);
966                 } else {
967                         continue;
968                 }
969         }
970
971         ao2_iterator_destroy(&i);
972
973         /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
974         if (res) {
975                 ast_json_unref(json);
976                 json = NULL;
977         }
978
979         return json;
980 }
981
982 int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
983 {
984         const struct ast_sorcery_object_details *details = object;
985         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
986         RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
987         struct ast_variable *field;
988         int res = 0;
989
990         if (!object_type) {
991                 return -1;
992         }
993
994         if (object_type->transform && (transformed = object_type->transform(objectset))) {
995                 field = transformed;
996         } else {
997                 field = objectset;
998         }
999
1000         for (; field; field = field->next) {
1001                 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1002                         break;
1003                 }
1004         }
1005
1006         if (!res && object_type->apply) {
1007                 res = object_type->apply(sorcery, object);
1008         }
1009
1010         return res;
1011 }
1012
1013 static const struct ast_variable *sorcery_find_field(const struct ast_variable *fields, const char *name)
1014 {
1015         const struct ast_variable *field;
1016
1017         /* Search the linked list of fields to find the correct one */
1018         for (field = fields; field; field = field->next) {
1019                 if (!strcmp(field->name, name)) {
1020                         return field;
1021                 }
1022         }
1023
1024         return NULL;
1025 }
1026
1027 int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1028 {
1029         const struct ast_variable *field;
1030         int res = 0;
1031
1032         *changes = NULL;
1033
1034         /* Unless the ast_variable list changes when examined... it can't differ from itself */
1035         if (original == modified) {
1036                 return 0;
1037         }
1038
1039         for (field = modified; field; field = field->next) {
1040                 const struct ast_variable *old = sorcery_find_field(original, field->name);
1041
1042                 if (!old || strcmp(old->value, field->value)) {
1043                         struct ast_variable *tmp;
1044
1045                         if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1046                                 res = -1;
1047                                 break;
1048                         }
1049
1050                         tmp->next = *changes;
1051                         *changes = tmp;
1052                 }
1053         }
1054
1055         /* If an error occurred do not return a partial changeset */
1056         if (res) {
1057                 ast_variables_destroy(*changes);
1058                 *changes = NULL;
1059         }
1060
1061         return res;
1062 }
1063
1064 static void sorcery_object_destructor(void *object)
1065 {
1066         struct ast_sorcery_object_details *details = object;
1067
1068         if (details->object->destructor) {
1069                 details->object->destructor(object);
1070         }
1071
1072         ast_variables_destroy(details->object->extended);
1073         ast_free(details->object->id);
1074 }
1075
1076 void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1077 {
1078         void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
1079         struct ast_sorcery_object_details *details = object;
1080
1081         if (!object) {
1082                 return NULL;
1083         }
1084
1085         details->object = object + size;
1086         details->object->destructor = destructor;
1087
1088         return object;
1089 }
1090
1091 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1092 {
1093         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1094         struct ast_sorcery_object_details *details;
1095
1096         if (!object_type || !object_type->type.item_alloc ||
1097                 !(details = object_type->type.item_alloc(id))) {
1098                 return NULL;
1099         }
1100
1101         if (ast_strlen_zero(id)) {
1102                 char uuid[AST_UUID_STR_LEN];
1103
1104                 ast_uuid_generate_str(uuid, sizeof(uuid));
1105                 details->object->id = ast_strdup(uuid);
1106         } else {
1107                 details->object->id = ast_strdup(id);
1108         }
1109
1110         ast_copy_string(details->object->type, type, sizeof(details->object->type));
1111
1112         if (aco_set_defaults(&object_type->type, id, details)) {
1113                 ao2_ref(details, -1);
1114                 return NULL;
1115         }
1116
1117         return details;
1118 }
1119
1120 void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1121 {
1122         const struct ast_sorcery_object_details *details = object;
1123         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1124         struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
1125         RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1126         int res = 0;
1127
1128         if (!copy) {
1129                 return NULL;
1130         } else if (object_type->copy) {
1131                 res = object_type->copy(object, copy);
1132         } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1133                 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1134         } else {
1135                 /* No native copy available and could not create an objectset, this copy has failed */
1136                 res = -1;
1137         }
1138
1139         if (res) {
1140                 ao2_cleanup(copy);
1141                 copy = NULL;
1142         }
1143
1144         return copy;
1145 }
1146
1147 int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1148 {
1149         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
1150
1151         *changes = NULL;
1152
1153         if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1154                 return -1;
1155         }
1156
1157         if (original == modified) {
1158                 return 0;
1159         } else if (!object_type->diff) {
1160                 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1161                 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1162
1163                 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1164                 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1165
1166                 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1167         } else {
1168                 return object_type->diff(original, modified, changes);
1169         }
1170 }
1171
1172 /*! \brief Structure used when calling create, update, or delete */
1173 struct sorcery_details {
1174         /*! \brief Pointer to the sorcery instance */
1175         const struct ast_sorcery *sorcery;
1176         /*! \brief Pointer to the object itself */
1177         void *obj;
1178 };
1179
1180 /*! \brief Internal function used to create an object in caching wizards */
1181 static int sorcery_cache_create(void *obj, void *arg, int flags)
1182 {
1183         const struct ast_sorcery_object_wizard *object_wizard = obj;
1184         const struct sorcery_details *details = arg;
1185
1186         if (!object_wizard->caching || !object_wizard->wizard->create) {
1187                 return 0;
1188         }
1189
1190         object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj);
1191
1192         return 0;
1193 }
1194
1195 void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1196 {
1197         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1198         void *object = NULL;
1199         struct ao2_iterator i;
1200         struct ast_sorcery_object_wizard *wizard;
1201         unsigned int cached = 0;
1202
1203         if (!object_type || ast_strlen_zero(id)) {
1204                 return NULL;
1205         }
1206
1207         i = ao2_iterator_init(object_type->wizards, 0);
1208         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1209                 if (wizard->wizard->retrieve_id &&
1210                         !(object = wizard->wizard->retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1211                         continue;
1212                 }
1213
1214                 cached = wizard->caching;
1215
1216                 ao2_ref(wizard, -1);
1217                 break;
1218         }
1219         ao2_iterator_destroy(&i);
1220
1221         if (!cached && object) {
1222                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1223         }
1224
1225         return object;
1226 }
1227
1228 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1229 {
1230         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1231         void *object = NULL;
1232         struct ao2_iterator i;
1233         struct ast_sorcery_object_wizard *wizard;
1234         unsigned int cached = 0;
1235
1236         if (!object_type) {
1237                 return NULL;
1238         }
1239
1240         /* If returning multiple objects create a container to store them in */
1241         if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1242                 if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1243                         return NULL;
1244                 }
1245         }
1246
1247         /* Inquire with the available wizards for retrieval */
1248         i = ao2_iterator_init(object_type->wizards, 0);
1249         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1250                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1251                         if (wizard->wizard->retrieve_multiple) {
1252                                 wizard->wizard->retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1253                         }
1254                 } else if (fields && wizard->wizard->retrieve_fields) {
1255                         if (wizard->wizard->retrieve_fields) {
1256                                 object = wizard->wizard->retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1257                         }
1258                 }
1259
1260                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
1261                         continue;
1262                 }
1263
1264                 cached = wizard->caching;
1265
1266                 ao2_ref(wizard, -1);
1267                 break;
1268         }
1269         ao2_iterator_destroy(&i);
1270
1271         /* If we are returning a single object and it came from a non-cache source create it in any caches */
1272         if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1273                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1274         }
1275
1276         return object;
1277 }
1278
1279 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1280 {
1281         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1282         struct ao2_container *objects;
1283         struct ao2_iterator i;
1284         struct ast_sorcery_object_wizard *wizard;
1285
1286         if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1287                 return NULL;
1288         }
1289
1290         i = ao2_iterator_init(object_type->wizards, 0);
1291         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1292                 if (!wizard->wizard->retrieve_regex) {
1293                         continue;
1294                 }
1295
1296                 wizard->wizard->retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1297         }
1298         ao2_iterator_destroy(&i);
1299
1300         return objects;
1301 }
1302
1303 /*! \brief Internal function which returns if the wizard has created the object */
1304 static int sorcery_wizard_create(void *obj, void *arg, int flags)
1305 {
1306         const struct ast_sorcery_object_wizard *object_wizard = obj;
1307         const struct sorcery_details *details = arg;
1308
1309         return (!object_wizard->caching && !object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
1310 }
1311
1312 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
1313 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
1314 {
1315         const struct ast_sorcery_object_type_observer *observer = obj;
1316
1317         if (observer->callbacks->created) {
1318                 observer->callbacks->created(arg);
1319         }
1320
1321         return 0;
1322 }
1323
1324 /*! \brief Internal callback function which notifies observers that an object has been created */
1325 static int sorcery_observers_notify_create(void *data)
1326 {
1327         struct sorcery_observer_invocation *invocation = data;
1328
1329         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
1330         ao2_cleanup(invocation);
1331
1332         return 0;
1333 }
1334
1335 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
1336 {
1337         const struct ast_sorcery_object_details *details = object;
1338         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1339         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1340         struct sorcery_details sdetails = {
1341                 .sorcery = sorcery,
1342                 .obj = object,
1343         };
1344
1345         if (!object_type) {
1346                 return -1;
1347         }
1348
1349         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
1350                 ao2_container_count(object_type->observers)) {
1351                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1352
1353                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
1354                         ao2_cleanup(invocation);
1355                 }
1356         }
1357
1358         return object_wizard ? 0 : -1;
1359 }
1360
1361 /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
1362 static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
1363 {
1364         const struct ast_sorcery_object_type_observer *observer = obj;
1365
1366         if (observer->callbacks->updated) {
1367                 observer->callbacks->updated(arg);
1368         }
1369
1370         return 0;
1371 }
1372
1373 /*! \brief Internal callback function which notifies observers that an object has been updated */
1374 static int sorcery_observers_notify_update(void *data)
1375 {
1376         struct sorcery_observer_invocation *invocation = data;
1377
1378         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
1379         ao2_cleanup(invocation);
1380
1381         return 0;
1382 }
1383
1384 /*! \brief Internal function which returns if a wizard has updated the object */
1385 static int sorcery_wizard_update(void *obj, void *arg, int flags)
1386 {
1387         const struct ast_sorcery_object_wizard *object_wizard = obj;
1388         const struct sorcery_details *details = arg;
1389
1390         return (object_wizard->wizard->update && !object_wizard->wizard->update(details->sorcery, object_wizard->data, details->obj) &&
1391                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1392 }
1393
1394 int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
1395 {
1396         const struct ast_sorcery_object_details *details = object;
1397         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1398         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1399         struct sorcery_details sdetails = {
1400                 .sorcery = sorcery,
1401                 .obj = object,
1402         };
1403
1404         if (!object_type) {
1405                 return -1;
1406         }
1407
1408         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
1409                 ao2_container_count(object_type->observers)) {
1410                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1411
1412                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
1413                         ao2_cleanup(invocation);
1414                 }
1415         }
1416
1417         return object_wizard ? 0 : -1;
1418 }
1419
1420 /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
1421 static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
1422 {
1423         const struct ast_sorcery_object_type_observer *observer = obj;
1424
1425         if (observer->callbacks->deleted) {
1426                 observer->callbacks->deleted(arg);
1427         }
1428
1429         return 0;
1430 }
1431
1432 /*! \brief Internal callback function which notifies observers that an object has been deleted */
1433 static int sorcery_observers_notify_delete(void *data)
1434 {
1435         struct sorcery_observer_invocation *invocation = data;
1436
1437         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
1438         ao2_cleanup(invocation);
1439
1440         return 0;
1441 }
1442
1443 /*! \brief Internal function which returns if a wizard has deleted the object */
1444 static int sorcery_wizard_delete(void *obj, void *arg, int flags)
1445 {
1446         const struct ast_sorcery_object_wizard *object_wizard = obj;
1447         const struct sorcery_details *details = arg;
1448
1449         return (object_wizard->wizard->delete && !object_wizard->wizard->delete(details->sorcery, object_wizard->data, details->obj) &&
1450                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1451 }
1452
1453 int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
1454 {
1455         const struct ast_sorcery_object_details *details = object;
1456         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1457         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1458         struct sorcery_details sdetails = {
1459                 .sorcery = sorcery,
1460                 .obj = object,
1461         };
1462
1463         if (!object_type) {
1464                 return -1;
1465         }
1466
1467         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
1468                 ao2_container_count(object_type->observers)) {
1469                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1470
1471                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
1472                         ao2_cleanup(invocation);
1473                 }
1474         }
1475
1476         return object_wizard ? 0 : -1;
1477 }
1478
1479 void ast_sorcery_unref(struct ast_sorcery *sorcery)
1480 {
1481         ao2_cleanup(sorcery);
1482 }
1483
1484 const char *ast_sorcery_object_get_id(const void *object)
1485 {
1486         const struct ast_sorcery_object_details *details = object;
1487         return details->object->id;
1488 }
1489
1490 const char *ast_sorcery_object_get_type(const void *object)
1491 {
1492         const struct ast_sorcery_object_details *details = object;
1493         return details->object->type;
1494 }
1495
1496 const char *ast_sorcery_object_get_extended(const void *object, const char *name)
1497 {
1498         const struct ast_sorcery_object_details *details = object;
1499         struct ast_variable *field;
1500
1501         for (field = details->object->extended; field; field = field->next) {
1502                 if (!strcmp(field->name + 1, name)) {
1503                         return field->value;
1504                 }
1505         }
1506
1507         return NULL;
1508 }
1509
1510 int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
1511 {
1512         RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
1513         struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
1514         const struct ast_sorcery_object_details *details = object;
1515
1516         if (!extended) {
1517                 return -1;
1518         }
1519
1520         for (field = details->object->extended; field; previous = field, field = field->next) {
1521                 if (!strcmp(field->name, name)) {
1522                         if (previous) {
1523                                 previous->next = field->next;
1524                         } else {
1525                                 details->object->extended = field->next;
1526                         }
1527                         field->next = NULL;
1528                         break;
1529                 }
1530         }
1531
1532         extended->next = details->object->extended;
1533         details->object->extended = extended;
1534
1535         return 0;
1536 }
1537
1538 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1539 {
1540         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1541         struct ast_sorcery_object_type_observer *observer;
1542         int res;
1543
1544         if (!object_type || !callbacks) {
1545                 return -1;
1546         }
1547
1548         if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
1549                 return -1;
1550         }
1551
1552         observer->callbacks = callbacks;
1553         res = 0;
1554         if (!ao2_link(object_type->observers, observer)) {
1555                 res = -1;
1556         }
1557         ao2_ref(observer, -1);
1558
1559         return res;
1560 }
1561
1562 /*! \brief Internal callback function for removing an observer */
1563 static int sorcery_observer_remove(void *obj, void *arg, int flags)
1564 {
1565         const struct ast_sorcery_object_type_observer *observer = obj;
1566
1567         return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
1568 }
1569
1570 void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1571 {
1572         RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
1573         struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
1574
1575         if (!sorcery) {
1576                 return;
1577         }
1578         object_type = ao2_find(sorcery->types, type, OBJ_KEY);
1579         if (!object_type) {
1580                 return;
1581         }
1582
1583         ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
1584                 sorcery_observer_remove, cbs);
1585 }