sorcery: Make is_object_field_registered handle field names that are regexes.
[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 Number of buckets for instances (should be prime for performance reasons) */
58 #define INSTANCE_BUCKETS 17
59
60 /*! \brief Number of buckets for object fields (should be prime for performance reasons) */
61 #define OBJECT_FIELD_BUCKETS 29
62
63 /*! \brief Thread pool for observers */
64 static struct ast_threadpool *threadpool;
65
66 /*! \brief Structure for internal sorcery object information */
67 struct ast_sorcery_object {
68         /*! \brief Unique identifier of this object */
69         char *id;
70
71         /*! \brief Type of object */
72         char type[MAX_OBJECT_TYPE];
73
74         /*! \brief Optional object destructor */
75         ao2_destructor_fn destructor;
76
77         /*! \brief Extended object fields */
78         struct ast_variable *extended;
79 };
80
81 /*! \brief Structure for registered object type */
82 struct ast_sorcery_object_type {
83         /*! \brief Unique name of the object type */
84         char name[MAX_OBJECT_TYPE];
85
86         /*! \brief Optional transformation callback */
87         sorcery_transform_handler transform;
88
89         /*! \brief Optional object set apply callback */
90         sorcery_apply_handler apply;
91
92         /*! \brief Optional object copy callback */
93         sorcery_copy_handler copy;
94
95         /*! \brief Optional object diff callback */
96         sorcery_diff_handler diff;
97
98         /*! \brief Wizard instances */
99         struct ao2_container *wizards;
100
101         /*! \brief Object fields */
102         struct ao2_container *fields;
103
104         /*! \brief Configuration framework general information */
105         struct aco_info *info;
106
107         /*! \brief Configuration framework file information */
108         struct aco_file *file;
109
110         /*! \brief Type details */
111         struct aco_type type;
112
113         /*! \brief Observers */
114         struct ao2_container *observers;
115
116         /*! \brief Serializer for observers */
117         struct ast_taskprocessor *serializer;
118
119         /*! \brief Specifies if object type is reloadable or not */
120         unsigned int reloadable:1;
121 };
122
123 /*! \brief Structure for registered object type observer */
124 struct ast_sorcery_object_type_observer {
125         /*! \brief Pointer to the observer implementation */
126         const struct ast_sorcery_observer *callbacks;
127 };
128
129 /*! \brief Structure used for observer invocations */
130 struct sorcery_observer_invocation {
131         /*! \brief Pointer to the object type */
132         struct ast_sorcery_object_type *object_type;
133
134         /*! \brief Pointer to the object */
135         void *object;
136 };
137
138 /*! \brief Structure for registered object field */
139 struct ast_sorcery_object_field {
140         /*! \brief Name of the field */
141         char name[MAX_OBJECT_FIELD];
142
143         /*! \brief The compiled name regex if name is a regex */
144         regex_t *name_regex;
145
146         /*! \brief Callback function for translation of a single value */
147         sorcery_field_handler handler;
148
149         /*! \brief Callback function for translation of multiple values */
150         sorcery_fields_handler multiple_handler;
151
152         /*! \brief Position of the field */
153         intptr_t args[];
154 };
155
156 /*! \brief Structure for a wizard instance which operates on objects */
157 struct ast_sorcery_object_wizard {
158         /*! \brief Wizard interface itself */
159         struct ast_sorcery_wizard *wizard;
160
161         /*! \brief Unique data for the wizard */
162         void *data;
163
164         /*! \brief Wizard is acting as an object cache */
165         unsigned int caching:1;
166 };
167
168 /*! \brief Full structure for sorcery */
169 struct ast_sorcery {
170         /*! \brief Container for known object types */
171         struct ao2_container *types;
172         /*! \brief The name of the module owning this sorcery instance */
173         char module_name[0];
174 };
175
176 /*! \brief Structure for passing load/reload details */
177 struct sorcery_load_details {
178         /*! \brief Sorcery structure in use */
179         const struct ast_sorcery *sorcery;
180
181         /*! \brief Type of object being loaded */
182         const char *type;
183
184         /*! \brief Whether this is a reload or not */
185         unsigned int reload:1;
186 };
187
188 /*! \brief Registered sorcery wizards */
189 static struct ao2_container *wizards;
190
191 /*! \brief Registered sorcery instances */
192 static struct ao2_container *instances;
193
194 static int int_handler_fn(const void *obj, const intptr_t *args, char **buf)
195 {
196         int *field = (int *)(obj + args[0]);
197         return (ast_asprintf(buf, "%d", *field) < 0) ? -1 : 0;
198 }
199
200 static int uint_handler_fn(const void *obj, const intptr_t *args, char **buf)
201 {
202         unsigned int *field = (unsigned int *)(obj + args[0]);
203         return (ast_asprintf(buf, "%u", *field) < 0) ? -1 : 0;
204 }
205
206 static int double_handler_fn(const void *obj, const intptr_t *args, char **buf)
207 {
208         double *field = (double *)(obj + args[0]);
209         return (ast_asprintf(buf, "%f", *field) < 0) ? -1 : 0;
210 }
211
212 static int stringfield_handler_fn(const void *obj, const intptr_t *args, char **buf)
213 {
214         ast_string_field *field = (const char **)(obj + args[0]);
215         return !(*buf = ast_strdup(*field)) ? -1 : 0;
216 }
217
218 static int bool_handler_fn(const void *obj, const intptr_t *args, char **buf)
219 {
220         unsigned int *field = (unsigned int *)(obj + args[0]);
221         return !(*buf = ast_strdup(*field ? "true" : "false")) ? -1 : 0;
222 }
223
224 static int sockaddr_handler_fn(const void *obj, const intptr_t *args, char **buf)
225 {
226         struct ast_sockaddr *field = (struct ast_sockaddr *)(obj + args[0]);
227         return !(*buf = ast_strdup(ast_sockaddr_stringify(field))) ? -1 : 0;
228 }
229
230 static int chararray_handler_fn(const void *obj, const intptr_t *args, char **buf)
231 {
232         char *field = (char *)(obj + args[0]);
233         return !(*buf = ast_strdup(field)) ? -1 : 0;
234 }
235
236 static int codec_handler_fn(const void *obj, const intptr_t *args, char **buf)
237 {
238         struct ast_str *codec_buf = ast_str_alloca(64);
239         struct ast_format_cap **cap = (struct ast_format_cap **)(obj + args[0]);
240         return !(*buf = ast_strdup(ast_format_cap_get_names(*cap, &codec_buf)));
241 }
242
243 static sorcery_field_handler sorcery_field_default_handler(enum aco_option_type type)
244 {
245         switch(type) {
246         case OPT_BOOL_T: return bool_handler_fn;
247         case OPT_CHAR_ARRAY_T: return chararray_handler_fn;
248         case OPT_CODEC_T: return codec_handler_fn;
249         case OPT_DOUBLE_T: return double_handler_fn;
250         case OPT_INT_T: return int_handler_fn;
251         case OPT_SOCKADDR_T: return sockaddr_handler_fn;
252         case OPT_STRINGFIELD_T: return stringfield_handler_fn;
253         case OPT_UINT_T: return uint_handler_fn;
254
255         default:
256         case OPT_CUSTOM_T: return NULL;
257         }
258
259         return NULL;
260 }
261
262 /*! \brief Hashing function for sorcery wizards */
263 static int sorcery_wizard_hash(const void *obj, const int flags)
264 {
265         const struct ast_sorcery_wizard *object;
266         const char *key;
267
268         switch (flags & OBJ_SEARCH_MASK) {
269         case OBJ_SEARCH_KEY:
270                 key = obj;
271                 break;
272         case OBJ_SEARCH_OBJECT:
273                 object = obj;
274                 key = object->name;
275                 break;
276         default:
277                 ast_assert(0);
278                 return 0;
279         }
280         return ast_str_hash(key);
281 }
282
283 /*! \brief Comparator function for sorcery wizards */
284 static int sorcery_wizard_cmp(void *obj, void *arg, int flags)
285 {
286         const struct ast_sorcery_wizard *object_left = obj;
287         const struct ast_sorcery_wizard *object_right = arg;
288         const char *right_key = arg;
289         int cmp;
290
291         switch (flags & OBJ_SEARCH_MASK) {
292         case OBJ_SEARCH_OBJECT:
293                 right_key = object_right->name;
294                 /* Fall through */
295         case OBJ_SEARCH_KEY:
296                 cmp = strcmp(object_left->name, right_key);
297                 break;
298         case OBJ_SEARCH_PARTIAL_KEY:
299                 cmp = strncmp(object_left->name, right_key, strlen(right_key));
300                 break;
301         default:
302                 cmp = 0;
303                 break;
304         }
305         if (cmp) {
306                 return 0;
307         }
308         return CMP_MATCH;
309 }
310
311 /*! \brief Hashing function for sorcery wizards */
312 static int object_type_field_hash(const void *obj, const int flags)
313 {
314         const struct ast_sorcery_object_field *object_field;
315         const char *key;
316
317         switch (flags & OBJ_SEARCH_MASK) {
318         case OBJ_SEARCH_KEY:
319                 key = obj;
320                 break;
321         case OBJ_SEARCH_OBJECT:
322                 object_field = obj;
323                 key = object_field->name;
324                 break;
325         default:
326                 ast_assert(0);
327                 return 0;
328         }
329         return ast_str_hash(key);
330 }
331
332 static int object_type_field_cmp(void *obj, void *arg, int flags)
333 {
334         const struct ast_sorcery_object_field *field_left = obj;
335         const struct ast_sorcery_object_field *field_right = arg;
336         const char *right_key = arg;
337         int cmp;
338
339         switch (flags & OBJ_SEARCH_MASK) {
340         case OBJ_SEARCH_OBJECT:
341                 right_key = field_right->name;
342                 /* Fall through */
343         case OBJ_SEARCH_KEY:
344                 cmp = strcmp(field_left->name, right_key);
345                 break;
346         case OBJ_SEARCH_PARTIAL_KEY:
347                 cmp = strncmp(field_left->name, right_key, strlen(right_key));
348                 break;
349         default:
350                 cmp = 0;
351                 break;
352         }
353         if (cmp) {
354                 return 0;
355         }
356         return CMP_MATCH;
357 }
358
359 /*! \brief Cleanup function */
360 static void sorcery_exit(void)
361 {
362         ast_threadpool_shutdown(threadpool);
363         threadpool = NULL;
364 }
365
366 /*! \brief Cleanup function for graceful shutdowns */
367 static void sorcery_cleanup(void)
368 {
369         ao2_cleanup(wizards);
370         wizards = NULL;
371         ao2_cleanup(instances);
372         instances = NULL;
373 }
374
375 /*! \brief Compare function for sorcery instances */
376 static int sorcery_instance_cmp(void *obj, void *arg, int flags)
377 {
378         const struct ast_sorcery *object_left = obj;
379         const struct ast_sorcery *object_right = arg;
380         const char *right_key = arg;
381         int cmp;
382
383         switch (flags & OBJ_SEARCH_MASK) {
384         case OBJ_SEARCH_OBJECT:
385                 right_key = object_right->module_name;
386                 /* Fall through */
387         case OBJ_SEARCH_KEY:
388                 cmp = strcmp(object_left->module_name, right_key);
389                 break;
390         case OBJ_SEARCH_PARTIAL_KEY:
391                 cmp = strncmp(object_left->module_name, right_key, strlen(right_key));
392                 break;
393         default:
394                 cmp = 0;
395                 break;
396         }
397         if (cmp) {
398                 return 0;
399         }
400         return CMP_MATCH;
401 }
402
403 /*! \brief Hashing function for sorcery instances */
404 static int sorcery_instance_hash(const void *obj, const int flags)
405 {
406         const struct ast_sorcery *object;
407         const char *key;
408
409         switch (flags & OBJ_SEARCH_MASK) {
410         case OBJ_SEARCH_KEY:
411                 key = obj;
412                 break;
413         case OBJ_SEARCH_OBJECT:
414                 object = obj;
415                 key = object->module_name;
416                 break;
417         default:
418                 ast_assert(0);
419                 return 0;
420         }
421         return ast_str_hash(key);
422 }
423
424 int ast_sorcery_init(void)
425 {
426         struct ast_threadpool_options options = {
427                 .version = AST_THREADPOOL_OPTIONS_VERSION,
428                 .auto_increment = 1,
429                 .max_size = 0,
430                 .idle_timeout = 60,
431                 .initial_size = 0,
432         };
433         ast_assert(wizards == NULL);
434
435         if (!(threadpool = ast_threadpool_create("Sorcery", NULL, &options))) {
436                 threadpool = NULL;
437                 return -1;
438         }
439
440         if (!(wizards = ao2_container_alloc(WIZARD_BUCKETS, sorcery_wizard_hash, sorcery_wizard_cmp))) {
441                 ast_threadpool_shutdown(threadpool);
442                 return -1;
443         }
444
445         instances = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, INSTANCE_BUCKETS,
446                 sorcery_instance_hash, sorcery_instance_cmp);
447         if (!instances) {
448                 sorcery_cleanup();
449                 sorcery_exit();
450                 return -1;
451         }
452
453         ast_register_cleanup(sorcery_cleanup);
454         ast_register_atexit(sorcery_exit);
455
456         return 0;
457 }
458
459 int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
460 {
461         struct ast_sorcery_wizard *wizard;
462         int res = -1;
463
464         ast_assert(!ast_strlen_zero(interface->name));
465
466         ao2_lock(wizards);
467
468         if ((wizard = ao2_find(wizards, interface->name, OBJ_KEY | OBJ_NOLOCK))) {
469                 ast_log(LOG_WARNING, "Attempted to register sorcery wizard '%s' twice\n",
470                         interface->name);
471                 goto done;
472         }
473
474         if (!(wizard = ao2_alloc(sizeof(*wizard), NULL))) {
475                 goto done;
476         }
477
478         *wizard = *interface;
479         wizard->module = module;
480
481         ao2_link_flags(wizards, wizard, OBJ_NOLOCK);
482         res = 0;
483
484         ast_verb(2, "Sorcery registered wizard '%s'\n", interface->name);
485
486 done:
487         ao2_cleanup(wizard);
488         ao2_unlock(wizards);
489
490         return res;
491 }
492
493 int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
494 {
495         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, interface->name, OBJ_KEY | OBJ_UNLINK), ao2_cleanup);
496
497         if (wizard) {
498                 ast_verb(2, "Sorcery unregistered wizard '%s'\n", interface->name);
499                 return 0;
500         } else {
501                 return -1;
502         }
503 }
504
505 /*! \brief Destructor called when sorcery structure is destroyed */
506 static void sorcery_destructor(void *obj)
507 {
508         struct ast_sorcery *sorcery = obj;
509
510         ao2_cleanup(sorcery->types);
511 }
512
513 /*! \brief Hashing function for sorcery types */
514 static int sorcery_type_hash(const void *obj, const int flags)
515 {
516         const struct ast_sorcery_object_type *object;
517         const char *key;
518
519         switch (flags & OBJ_SEARCH_MASK) {
520         case OBJ_SEARCH_KEY:
521                 key = obj;
522                 break;
523         case OBJ_SEARCH_OBJECT:
524                 object = obj;
525                 key = object->name;
526                 break;
527         default:
528                 ast_assert(0);
529                 return 0;
530         }
531         return ast_str_hash(key);
532 }
533
534 /*! \brief Comparator function for sorcery types */
535 static int sorcery_type_cmp(void *obj, void *arg, int flags)
536 {
537         const struct ast_sorcery_object_type *object_left = obj;
538         const struct ast_sorcery_object_type *object_right = arg;
539         const char *right_key = arg;
540         int cmp;
541
542         switch (flags & OBJ_SEARCH_MASK) {
543         case OBJ_SEARCH_OBJECT:
544                 right_key = object_right->name;
545                 /* Fall through */
546         case OBJ_SEARCH_KEY:
547                 cmp = strcmp(object_left->name, right_key);
548                 break;
549         case OBJ_SEARCH_PARTIAL_KEY:
550                 cmp = strncmp(object_left->name, right_key, strlen(right_key));
551                 break;
552         default:
553                 cmp = 0;
554                 break;
555         }
556         if (cmp) {
557                 return 0;
558         }
559         return CMP_MATCH;
560 }
561
562 struct ast_sorcery *__ast_sorcery_open(const char *module_name)
563 {
564         struct ast_sorcery *sorcery;
565
566         ast_assert(module_name != NULL);
567
568         ao2_wrlock(instances);
569         if ((sorcery = ao2_find(instances, module_name, OBJ_SEARCH_KEY | OBJ_NOLOCK))) {
570                 goto done;
571         }
572
573         if (!(sorcery = ao2_alloc(sizeof(*sorcery) + strlen(module_name) + 1, sorcery_destructor))) {
574                 goto done;
575         }
576
577         if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
578                 ao2_ref(sorcery, -1);
579                 sorcery = NULL;
580                 goto done;
581         }
582
583         strcpy(sorcery->module_name, module_name); /* Safe */
584
585         if (__ast_sorcery_apply_config(sorcery, module_name, module_name) == AST_SORCERY_APPLY_FAIL) {
586                 ast_log(LOG_ERROR, "Error attempting to apply configuration %s to sorcery.\n", module_name);
587                 ao2_cleanup(sorcery);
588                 sorcery = NULL;
589                 goto done;
590         }
591
592         ao2_link_flags(instances, sorcery, OBJ_NOLOCK);
593
594 done:
595         ao2_unlock(instances);
596         return sorcery;
597 }
598
599 /*! \brief Search function for sorcery instances */
600 struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name)
601 {
602         return ao2_find(instances, module_name, OBJ_SEARCH_KEY);
603 }
604
605 /*! \brief Destructor function for object types */
606 static void sorcery_object_type_destructor(void *obj)
607 {
608         struct ast_sorcery_object_type *object_type = obj;
609
610         ao2_cleanup(object_type->wizards);
611         ao2_cleanup(object_type->fields);
612         ao2_cleanup(object_type->observers);
613
614         if (object_type->info) {
615                 aco_info_destroy(object_type->info);
616                 ast_free(object_type->info);
617         }
618
619         ast_free(object_type->file);
620
621         ast_taskprocessor_unreference(object_type->serializer);
622 }
623
624 /*! \brief Internal function which allocates an object type structure */
625 static struct ast_sorcery_object_type *sorcery_object_type_alloc(const char *type, const char *module)
626 {
627         struct ast_sorcery_object_type *object_type;
628         char uuid[AST_UUID_STR_LEN];
629
630         if (!(object_type = ao2_alloc(sizeof(*object_type), sorcery_object_type_destructor))) {
631                 return NULL;
632         }
633
634         /* Order matters for object wizards */
635         if (!(object_type->wizards = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, sorcery_wizard_cmp))) {
636                 ao2_ref(object_type, -1);
637                 return NULL;
638         }
639
640         if (!(object_type->fields = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, OBJECT_FIELD_BUCKETS,
641                                         object_type_field_hash, object_type_field_cmp))) {
642                 ao2_ref(object_type, -1);
643                 return NULL;
644         }
645
646         if (!(object_type->observers = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, 1, NULL, NULL))) {
647                 ao2_ref(object_type, -1);
648                 return NULL;
649         }
650
651         if (!(object_type->info = ast_calloc(1, sizeof(*object_type->info) + 2 * sizeof(object_type->info->files[0])))) {
652                 ao2_ref(object_type, -1);
653                 return NULL;
654         }
655
656         if (!(object_type->file = ast_calloc(1, sizeof(*object_type->file) + 2 * sizeof(object_type->file->types[0])))) {
657                 ao2_ref(object_type, -1);
658                 return NULL;
659         }
660
661         if (!ast_uuid_generate_str(uuid, sizeof(uuid))) {
662                 ao2_ref(object_type, -1);
663                 return NULL;
664         }
665
666         if (!(object_type->serializer = ast_threadpool_serializer(uuid, threadpool))) {
667                 ao2_ref(object_type, -1);
668                 return NULL;
669         }
670
671         object_type->info->files[0] = object_type->file;
672         object_type->info->files[1] = NULL;
673         object_type->info->module = module;
674
675         ast_copy_string(object_type->name, type, sizeof(object_type->name));
676
677         return object_type;
678 }
679
680 /*! \brief Object wizard destructor */
681 static void sorcery_object_wizard_destructor(void *obj)
682 {
683         struct ast_sorcery_object_wizard *object_wizard = obj;
684
685         if (object_wizard->data) {
686                 object_wizard->wizard->close(object_wizard->data);
687         }
688
689         if (object_wizard->wizard) {
690                 ast_module_unref(object_wizard->wizard->module);
691         }
692
693         ao2_cleanup(object_wizard->wizard);
694 }
695
696 /*! \brief Internal function which creates an object type and adds a wizard mapping */
697 static enum ast_sorcery_apply_result sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
698                 const char *type, const char *module, const char *name, const char *data, unsigned int caching)
699 {
700         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
701         RAII_VAR(struct ast_sorcery_wizard *, wizard, ao2_find(wizards, name, OBJ_KEY), ao2_cleanup);
702         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, ao2_alloc(sizeof(*object_wizard), sorcery_object_wizard_destructor), ao2_cleanup);
703         int created = 0;
704
705         if (!wizard || !object_wizard) {
706                 return AST_SORCERY_APPLY_FAIL;
707         }
708
709         if (!object_type) {
710                 if (!(object_type = sorcery_object_type_alloc(type, module))) {
711                         return AST_SORCERY_APPLY_FAIL;
712                 }
713                 created = 1;
714         }
715
716         if (!created) {
717                 struct ast_sorcery_wizard *found;
718
719                 found = ao2_find(object_type->wizards, wizard, OBJ_SEARCH_OBJECT);
720                 if (found) {
721                         ast_debug(1, "Wizard %s already applied to object type %s\n",
722                                         wizard->name, object_type->name);
723                         ao2_cleanup(found);
724                         return AST_SORCERY_APPLY_DUPLICATE;
725                 }
726         }
727
728         if (wizard->open && !(object_wizard->data = wizard->open(data))) {
729                 return AST_SORCERY_APPLY_FAIL;
730         }
731
732         ast_module_ref(wizard->module);
733
734         object_wizard->wizard = ao2_bump(wizard);
735         object_wizard->caching = caching;
736
737         ao2_link(object_type->wizards, object_wizard);
738
739         if (created) {
740                 ao2_link(sorcery->types, object_type);
741         }
742
743         return AST_SORCERY_APPLY_SUCCESS;
744 }
745
746 enum ast_sorcery_apply_result  __ast_sorcery_apply_config(struct ast_sorcery *sorcery, const char *name, const char *module)
747 {
748         struct ast_flags flags = { 0 };
749         struct ast_config *config = ast_config_load2("sorcery.conf", "sorcery", flags);
750         struct ast_variable *mapping;
751         int res = AST_SORCERY_APPLY_SUCCESS;
752
753         if (!config) {
754                 return AST_SORCERY_APPLY_NO_CONFIGURATION;
755         }
756
757         if (config == CONFIG_STATUS_FILEINVALID) {
758                 return AST_SORCERY_APPLY_FAIL;
759         }
760
761         for (mapping = ast_variable_browse(config, name); mapping; mapping = mapping->next) {
762                 RAII_VAR(char *, mapping_name, ast_strdup(mapping->name), ast_free);
763                 RAII_VAR(char *, mapping_value, ast_strdup(mapping->value), ast_free);
764                 char *options = mapping_name;
765                 char *type = strsep(&options, "/");
766                 char *data = mapping_value;
767                 char *wizard = strsep(&data, ",");
768                 unsigned int caching = 0;
769
770                 /* If no object type or wizard exists just skip, nothing we can do */
771                 if (ast_strlen_zero(type) || ast_strlen_zero(wizard)) {
772                         continue;
773                 }
774
775                 /* If the wizard is configured as a cache treat it as such */
776                 if (!ast_strlen_zero(options) && strstr(options, "cache")) {
777                         caching = 1;
778                 }
779
780                 /* Any error immediately causes us to stop */
781                 if (sorcery_apply_wizard_mapping(sorcery, type, module, wizard, data, caching) == AST_SORCERY_APPLY_FAIL) {
782                         res = AST_SORCERY_APPLY_FAIL;
783                         break;
784                 }
785         }
786
787         ast_config_destroy(config);
788
789         return res;
790 }
791
792 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)
793 {
794         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
795
796         /* Defaults can not be added if any existing mapping exists */
797         if (object_type) {
798                 return AST_SORCERY_APPLY_DEFAULT_UNNECESSARY;
799         }
800
801         return sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0);
802 }
803
804 static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
805 {
806         return ast_sorcery_object_set_extended(obj, var->name, var->value);
807 }
808
809 static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields)
810 {
811         const struct ast_sorcery_object_details *details = obj;
812
813         if (details->object->extended) {
814                 *fields = ast_variables_dup(details->object->extended);
815         } else {
816                 *fields = NULL;
817         }
818
819         return 0;
820 }
821
822 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)
823 {
824         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
825
826         if (!object_type || object_type->type.item_alloc) {
827                 return -1;
828         }
829
830         object_type->type.name = object_type->name;
831         object_type->type.type = ACO_ITEM;
832         object_type->type.category = ".?";
833         object_type->type.item_alloc = alloc;
834         object_type->type.hidden = hidden;
835
836         object_type->reloadable = reloadable;
837         object_type->transform = transform;
838         object_type->apply = apply;
839         object_type->file->types[0] = &object_type->type;
840         object_type->file->types[1] = NULL;
841
842         if (aco_info_init(object_type->info)) {
843                 return -1;
844         }
845
846         if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) {
847                 return -1;
848         }
849
850         return 0;
851 }
852
853 void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
854 {
855         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
856
857         if (!object_type) {
858                 return;
859         }
860
861         object_type->copy = copy;
862 }
863
864 void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
865 {
866         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
867
868         if (!object_type) {
869                 return;
870         }
871
872         object_type->diff = diff;
873 }
874
875 static void sorcery_object_field_destructor(void *obj)
876 {
877         struct ast_sorcery_object_field *object_field = obj;
878
879         if (object_field->name_regex) {
880                 regfree(object_field->name_regex);
881         }
882 }
883
884 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)
885 {
886 #define MAX_REGEX_ERROR_LEN 128
887         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
888         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
889         int rc;
890
891         if (!object_type || !object_type->type.item_alloc || !config_handler
892                 || !(object_field = ao2_alloc(sizeof(*object_field), sorcery_object_field_destructor))) {
893                 return -1;
894         }
895
896         ast_copy_string(object_field->name, regex, sizeof(object_field->name));
897         object_field->multiple_handler = sorcery_handler;
898
899         if (!(object_field->name_regex = ast_calloc(1, sizeof(regex_t)))) {
900                 return -1;
901         }
902
903         if ((rc = regcomp(object_field->name_regex, regex, REG_EXTENDED | REG_NOSUB))) {
904                 char *regerr = ast_alloca(MAX_REGEX_ERROR_LEN);
905                 regerror(rc, object_field->name_regex, regerr, MAX_REGEX_ERROR_LEN);
906                 ast_log(LOG_ERROR, "Regular expression '%s' failed to compile: %s\n", regex, regerr);
907                 return -1;
908         }
909
910         ao2_link(object_type->fields, object_field);
911         __aco_option_register(object_type->info, regex, ACO_REGEX, object_type->file->types, "", OPT_CUSTOM_T, config_handler, 0, 1, 0);
912
913         return 0;
914 }
915
916 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,
917                                         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, ...)
918 {
919         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
920         RAII_VAR(struct ast_sorcery_object_field *, object_field, NULL, ao2_cleanup);
921         int pos;
922         va_list args;
923
924         if (!strcmp(type, "id") || !object_type || !object_type->type.item_alloc) {
925                 return -1;
926         }
927
928         if (!sorcery_handler) {
929                 sorcery_handler = sorcery_field_default_handler(opt_type);
930         }
931
932         if (!(object_field = ao2_alloc(sizeof(*object_field) + argc * sizeof(object_field->args[0]), NULL))) {
933                 return -1;
934         }
935
936         ast_copy_string(object_field->name, name, sizeof(object_field->name));
937         object_field->handler = sorcery_handler;
938         object_field->multiple_handler = multiple_handler;
939
940         va_start(args, argc);
941         for (pos = 0; pos < argc; pos++) {
942                 object_field->args[pos] = va_arg(args, size_t);
943         }
944         va_end(args);
945
946         if (!alias) {
947                 ao2_link(object_type->fields, object_field);
948         }
949
950         /* TODO: Improve this hack */
951         if (!argc) {
952                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc);
953         } else if (argc == 1) {
954                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
955                         object_field->args[0]);
956         } else if (argc == 2) {
957                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
958                         object_field->args[0], object_field->args[1]);
959         } else if (argc == 3) {
960                 __aco_option_register(object_type->info, name, ACO_EXACT, object_type->file->types, default_val, opt_type, config_handler, flags, no_doc, argc,
961                         object_field->args[0], object_field->args[1], object_field->args[2]);
962         } else {
963                 ast_assert(0); /* The hack... she does us no good for this */
964         }
965
966         return 0;
967 }
968
969 /*! \brief Retrieves whether or not the type is reloadable */
970 static int sorcery_reloadable(const struct ast_sorcery *sorcery, const char *type)
971 {
972         RAII_VAR(struct ast_sorcery_object_type *, object_type,
973                  ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
974         return object_type && object_type->reloadable;
975 }
976
977 static int sorcery_wizard_load(void *obj, void *arg, int flags)
978 {
979         struct ast_sorcery_object_wizard *wizard = obj;
980         struct sorcery_load_details *details = arg;
981         void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
982
983         if (details->reload && !sorcery_reloadable(details->sorcery, details->type)) {
984                 ast_log(LOG_NOTICE, "Type '%s' is not reloadable, "
985                         "maintaining previous values\n", details->type);
986                 return 0;
987         }
988
989         load = !details->reload ? wizard->wizard->load : wizard->wizard->reload;
990
991         if (load) {
992                 load(wizard->data, details->sorcery, details->type);
993         }
994
995         return 0;
996 }
997
998 /*! \brief Destructor for observer invocation */
999 static void sorcery_observer_invocation_destroy(void *obj)
1000 {
1001         struct sorcery_observer_invocation *invocation = obj;
1002
1003         ao2_cleanup(invocation->object_type);
1004         ao2_cleanup(invocation->object);
1005 }
1006
1007 /*! \brief Allocator function for observer invocation */
1008 static struct sorcery_observer_invocation *sorcery_observer_invocation_alloc(struct ast_sorcery_object_type *object_type, void *object)
1009 {
1010         struct sorcery_observer_invocation *invocation = ao2_alloc(sizeof(*invocation), sorcery_observer_invocation_destroy);
1011
1012         if (!invocation) {
1013                 return NULL;
1014         }
1015
1016         ao2_ref(object_type, +1);
1017         invocation->object_type = object_type;
1018
1019         if (object) {
1020                 ao2_ref(object, +1);
1021                 invocation->object = object;
1022         }
1023
1024         return invocation;
1025 }
1026
1027 /*! \brief Internal callback function which notifies an individual observer that an object type has been loaded */
1028 static int sorcery_observer_notify_loaded(void *obj, void *arg, int flags)
1029 {
1030         const struct ast_sorcery_object_type_observer *observer = obj;
1031
1032         if (observer->callbacks->loaded) {
1033                 observer->callbacks->loaded(arg);
1034         }
1035
1036         return 0;
1037 }
1038
1039 /*! \brief Internal callback function which notifies observers that an object type has been loaded */
1040 static int sorcery_observers_notify_loaded(void *data)
1041 {
1042         struct sorcery_observer_invocation *invocation = data;
1043
1044         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_loaded, invocation->object_type->name);
1045         ao2_cleanup(invocation);
1046
1047         return 0;
1048 }
1049
1050 static int sorcery_object_load(void *obj, void *arg, int flags)
1051 {
1052         struct ast_sorcery_object_type *type = obj;
1053         struct sorcery_load_details *details = arg;
1054
1055         details->type = type->name;
1056         ao2_callback(type->wizards, OBJ_NODATA, sorcery_wizard_load, details);
1057
1058         if (ao2_container_count(type->observers)) {
1059                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(type, NULL);
1060
1061                 if (invocation && ast_taskprocessor_push(type->serializer, sorcery_observers_notify_loaded, invocation)) {
1062                         ao2_cleanup(invocation);
1063                 }
1064         }
1065
1066         return 0;
1067 }
1068
1069 void ast_sorcery_load(const struct ast_sorcery *sorcery)
1070 {
1071         struct sorcery_load_details details = {
1072                 .sorcery = sorcery,
1073                 .reload = 0,
1074         };
1075
1076         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1077 }
1078
1079 void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
1080 {
1081         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1082         struct sorcery_load_details details = {
1083                 .sorcery = sorcery,
1084                 .reload = 0,
1085         };
1086
1087         if (!object_type) {
1088                 return;
1089         }
1090
1091         sorcery_object_load(object_type, &details, 0);
1092 }
1093
1094 void ast_sorcery_reload(const struct ast_sorcery *sorcery)
1095 {
1096         struct sorcery_load_details details = {
1097                 .sorcery = sorcery,
1098                 .reload = 1,
1099         };
1100
1101         ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
1102 }
1103
1104 void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
1105 {
1106         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1107         struct sorcery_load_details details = {
1108                 .sorcery = sorcery,
1109                 .reload = 1,
1110         };
1111
1112         if (!object_type) {
1113                 return;
1114         }
1115
1116         sorcery_object_load(object_type, &details, 0);
1117 }
1118
1119 void ast_sorcery_ref(struct ast_sorcery *sorcery)
1120 {
1121         ao2_ref(sorcery, +1);
1122 }
1123
1124 static struct ast_variable *get_single_field_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1125 {
1126         struct ast_variable *tmp = NULL;
1127         char *buf = NULL;
1128
1129         if (!object_field->handler) {
1130                 return NULL;
1131         }
1132
1133         if (!(object_field->handler(object, object_field->args, &buf))) {
1134                 tmp = ast_variable_new(object_field->name, S_OR(buf, ""), "");
1135         }
1136         ast_free(buf);
1137
1138         return tmp;
1139 }
1140
1141 static struct ast_variable *get_multiple_fields_as_var_list(const void *object, struct ast_sorcery_object_field *object_field)
1142 {
1143         struct ast_variable *tmp = NULL;
1144
1145         if (!object_field->multiple_handler) {
1146                 return NULL;
1147         }
1148
1149         if (object_field->multiple_handler(object, &tmp)) {
1150                 ast_variables_destroy(tmp);
1151                 tmp = NULL;
1152         }
1153
1154         return tmp;
1155 }
1156
1157 struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
1158         const void *object,     enum ast_sorcery_field_handler_flags flags)
1159 {
1160         const struct ast_sorcery_object_details *details = object;
1161         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1162         struct ao2_iterator i;
1163         struct ast_sorcery_object_field *object_field;
1164         struct ast_variable *head = NULL;
1165         struct ast_variable *tail = NULL;
1166
1167         if (!object_type) {
1168                 return NULL;
1169         }
1170
1171         i = ao2_iterator_init(object_type->fields, 0);
1172
1173         for (; (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1174                 struct ast_variable *tmp;
1175
1176                 switch (flags) {
1177                 case AST_HANDLER_PREFER_LIST:
1178                         if ((tmp = get_multiple_fields_as_var_list(object, object_field)) ||
1179                                 (tmp = get_single_field_as_var_list(object, object_field))) {
1180                                 break;
1181                         }
1182                         continue;
1183                 case AST_HANDLER_PREFER_STRING:
1184                         if ((tmp = get_single_field_as_var_list(object, object_field)) ||
1185                                 (tmp = get_multiple_fields_as_var_list(object, object_field))) {
1186                                 break;
1187                         }
1188                         continue;
1189                 case AST_HANDLER_ONLY_LIST:
1190                         if ((tmp = get_multiple_fields_as_var_list(object, object_field))) {
1191                                 break;
1192                         }
1193                         continue;
1194                 case AST_HANDLER_ONLY_STRING:
1195                         if ((tmp = get_single_field_as_var_list(object, object_field))) {
1196                                 break;
1197                         }
1198                         continue;
1199                 default:
1200                         continue;
1201                 }
1202
1203                 tail = ast_variable_list_append_hint(&head, tail, tmp);
1204         }
1205
1206         ao2_iterator_destroy(&i);
1207
1208         return head;
1209 }
1210
1211 struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object)
1212 {
1213         const struct ast_sorcery_object_details *details = object;
1214         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1215         struct ao2_iterator i;
1216         struct ast_sorcery_object_field *object_field;
1217         struct ast_json *json = ast_json_object_create();
1218         int res = 0;
1219
1220         if (!object_type || !json) {
1221                 return NULL;
1222         }
1223
1224         i = ao2_iterator_init(object_type->fields, 0);
1225
1226         for (; !res && (object_field = ao2_iterator_next(&i)); ao2_ref(object_field, -1)) {
1227                 if (object_field->multiple_handler) {
1228                         struct ast_variable *tmp = NULL;
1229                         struct ast_variable *field;
1230
1231                         if ((res = object_field->multiple_handler(object, &tmp))) {
1232                                 ast_variables_destroy(tmp);
1233                                 ao2_ref(object_field, -1);
1234                                 break;
1235                         }
1236
1237                         for (field = tmp; field; field = field->next) {
1238                                 struct ast_json *value = ast_json_string_create(field->value);
1239
1240                                 if (!value || ast_json_object_set(json, field->name, value)) {
1241                                         res = -1;
1242                                         break;
1243                                 }
1244                         }
1245
1246                         ast_variables_destroy(tmp);
1247                 } else if (object_field->handler) {
1248                         char *buf = NULL;
1249                         struct ast_json *value = NULL;
1250
1251                         if ((res = object_field->handler(object, object_field->args, &buf))
1252                                 || !(value = ast_json_string_create(buf))
1253                                 || ast_json_object_set(json, object_field->name, value)) {
1254                                 res = -1;
1255                         }
1256
1257                         ast_free(buf);
1258                 } else {
1259                         continue;
1260                 }
1261         }
1262
1263         ao2_iterator_destroy(&i);
1264
1265         /* If any error occurs we destroy the JSON object so a partial objectset is not returned */
1266         if (res) {
1267                 ast_json_unref(json);
1268                 json = NULL;
1269         }
1270
1271         return json;
1272 }
1273
1274 int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset)
1275 {
1276         const struct ast_sorcery_object_details *details = object;
1277         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1278         RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy);
1279         struct ast_variable *field;
1280         int res = 0;
1281
1282         if (!object_type) {
1283                 return -1;
1284         }
1285
1286         if (object_type->transform && (transformed = object_type->transform(objectset))) {
1287                 field = transformed;
1288         } else {
1289                 field = objectset;
1290         }
1291
1292         for (; field; field = field->next) {
1293                 if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) {
1294                         break;
1295                 }
1296         }
1297
1298         if (!res && object_type->apply) {
1299                 res = object_type->apply(sorcery, object);
1300         }
1301
1302         return res;
1303 }
1304
1305 static const struct ast_variable *sorcery_find_field(const struct ast_variable *fields, const char *name)
1306 {
1307         const struct ast_variable *field;
1308
1309         /* Search the linked list of fields to find the correct one */
1310         for (field = fields; field; field = field->next) {
1311                 if (!strcmp(field->name, name)) {
1312                         return field;
1313                 }
1314         }
1315
1316         return NULL;
1317 }
1318
1319 int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes)
1320 {
1321         const struct ast_variable *field;
1322         int res = 0;
1323
1324         *changes = NULL;
1325
1326         /* Unless the ast_variable list changes when examined... it can't differ from itself */
1327         if (original == modified) {
1328                 return 0;
1329         }
1330
1331         for (field = modified; field; field = field->next) {
1332                 const struct ast_variable *old = sorcery_find_field(original, field->name);
1333
1334                 if (!old || strcmp(old->value, field->value)) {
1335                         struct ast_variable *tmp;
1336
1337                         if (!(tmp = ast_variable_new(field->name, field->value, ""))) {
1338                                 res = -1;
1339                                 break;
1340                         }
1341
1342                         tmp->next = *changes;
1343                         *changes = tmp;
1344                 }
1345         }
1346
1347         /* If an error occurred do not return a partial changeset */
1348         if (res) {
1349                 ast_variables_destroy(*changes);
1350                 *changes = NULL;
1351         }
1352
1353         return res;
1354 }
1355
1356 static void sorcery_object_destructor(void *object)
1357 {
1358         struct ast_sorcery_object_details *details = object;
1359
1360         if (details->object->destructor) {
1361                 details->object->destructor(object);
1362         }
1363
1364         ast_variables_destroy(details->object->extended);
1365         ast_free(details->object->id);
1366 }
1367
1368 void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
1369 {
1370         void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
1371         struct ast_sorcery_object_details *details = object;
1372
1373         if (!object) {
1374                 return NULL;
1375         }
1376
1377         details->object = object + size;
1378         details->object->destructor = destructor;
1379
1380         return object;
1381 }
1382
1383 void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
1384 {
1385         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1386         struct ast_sorcery_object_details *details;
1387
1388         if (!object_type || !object_type->type.item_alloc ||
1389                 !(details = object_type->type.item_alloc(id))) {
1390                 return NULL;
1391         }
1392
1393         if (ast_strlen_zero(id)) {
1394                 char uuid[AST_UUID_STR_LEN];
1395
1396                 ast_uuid_generate_str(uuid, sizeof(uuid));
1397                 details->object->id = ast_strdup(uuid);
1398         } else {
1399                 details->object->id = ast_strdup(id);
1400         }
1401
1402         ast_copy_string(details->object->type, type, sizeof(details->object->type));
1403
1404         if (aco_set_defaults(&object_type->type, id, details)) {
1405                 ao2_ref(details, -1);
1406                 return NULL;
1407         }
1408
1409         return details;
1410 }
1411
1412 void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
1413 {
1414         const struct ast_sorcery_object_details *details = object;
1415         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1416         struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id);
1417         RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy);
1418         int res = 0;
1419
1420         if (!copy) {
1421                 return NULL;
1422         } else if (object_type->copy) {
1423                 res = object_type->copy(object, copy);
1424         } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
1425                 res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
1426         } else {
1427                 /* No native copy available and could not create an objectset, this copy has failed */
1428                 res = -1;
1429         }
1430
1431         if (res) {
1432                 ao2_cleanup(copy);
1433                 copy = NULL;
1434         }
1435
1436         return copy;
1437 }
1438
1439 int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
1440 {
1441         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
1442
1443         *changes = NULL;
1444
1445         if (strcmp(ast_sorcery_object_get_type(original), ast_sorcery_object_get_type(modified))) {
1446                 return -1;
1447         }
1448
1449         if (original == modified) {
1450                 return 0;
1451         } else if (!object_type->diff) {
1452                 RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
1453                 RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
1454
1455                 objectset1 = ast_sorcery_objectset_create(sorcery, original);
1456                 objectset2 = ast_sorcery_objectset_create(sorcery, modified);
1457
1458                 return ast_sorcery_changeset_create(objectset1, objectset2, changes);
1459         } else {
1460                 return object_type->diff(original, modified, changes);
1461         }
1462 }
1463
1464 /*! \brief Structure used when calling create, update, or delete */
1465 struct sorcery_details {
1466         /*! \brief Pointer to the sorcery instance */
1467         const struct ast_sorcery *sorcery;
1468         /*! \brief Pointer to the object itself */
1469         void *obj;
1470 };
1471
1472 /*! \brief Internal function used to create an object in caching wizards */
1473 static int sorcery_cache_create(void *obj, void *arg, int flags)
1474 {
1475         const struct ast_sorcery_object_wizard *object_wizard = obj;
1476         const struct sorcery_details *details = arg;
1477
1478         if (!object_wizard->caching || !object_wizard->wizard->create) {
1479                 return 0;
1480         }
1481
1482         object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj);
1483
1484         return 0;
1485 }
1486
1487 void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
1488 {
1489         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1490         void *object = NULL;
1491         struct ao2_iterator i;
1492         struct ast_sorcery_object_wizard *wizard;
1493         unsigned int cached = 0;
1494
1495         if (!object_type || ast_strlen_zero(id)) {
1496                 return NULL;
1497         }
1498
1499         i = ao2_iterator_init(object_type->wizards, 0);
1500         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1501                 if (wizard->wizard->retrieve_id &&
1502                         !(object = wizard->wizard->retrieve_id(sorcery, wizard->data, object_type->name, id))) {
1503                         continue;
1504                 }
1505
1506                 cached = wizard->caching;
1507
1508                 ao2_ref(wizard, -1);
1509                 break;
1510         }
1511         ao2_iterator_destroy(&i);
1512
1513         if (!cached && object) {
1514                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1515         }
1516
1517         return object;
1518 }
1519
1520 void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields)
1521 {
1522         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1523         void *object = NULL;
1524         struct ao2_iterator i;
1525         struct ast_sorcery_object_wizard *wizard;
1526         unsigned int cached = 0;
1527
1528         if (!object_type) {
1529                 return NULL;
1530         }
1531
1532         /* If returning multiple objects create a container to store them in */
1533         if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1534                 if (!(object = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1535                         return NULL;
1536                 }
1537         }
1538
1539         /* Inquire with the available wizards for retrieval */
1540         i = ao2_iterator_init(object_type->wizards, 0);
1541         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1542                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE)) {
1543                         if (wizard->wizard->retrieve_multiple) {
1544                                 wizard->wizard->retrieve_multiple(sorcery, wizard->data, object_type->name, object, fields);
1545                         }
1546                 } else if (fields && wizard->wizard->retrieve_fields) {
1547                         if (wizard->wizard->retrieve_fields) {
1548                                 object = wizard->wizard->retrieve_fields(sorcery, wizard->data, object_type->name, fields);
1549                         }
1550                 }
1551
1552                 if ((flags & AST_RETRIEVE_FLAG_MULTIPLE) || !object) {
1553                         continue;
1554                 }
1555
1556                 cached = wizard->caching;
1557
1558                 ao2_ref(wizard, -1);
1559                 break;
1560         }
1561         ao2_iterator_destroy(&i);
1562
1563         /* If we are returning a single object and it came from a non-cache source create it in any caches */
1564         if (!(flags & AST_RETRIEVE_FLAG_MULTIPLE) && !cached && object) {
1565                 ao2_callback(object_type->wizards, 0, sorcery_cache_create, object);
1566         }
1567
1568         return object;
1569 }
1570
1571 struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex)
1572 {
1573         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1574         struct ao2_container *objects;
1575         struct ao2_iterator i;
1576         struct ast_sorcery_object_wizard *wizard;
1577
1578         if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
1579                 return NULL;
1580         }
1581
1582         i = ao2_iterator_init(object_type->wizards, 0);
1583         for (; (wizard = ao2_iterator_next(&i)); ao2_ref(wizard, -1)) {
1584                 if (!wizard->wizard->retrieve_regex) {
1585                         continue;
1586                 }
1587
1588                 wizard->wizard->retrieve_regex(sorcery, wizard->data, object_type->name, objects, regex);
1589         }
1590         ao2_iterator_destroy(&i);
1591
1592         return objects;
1593 }
1594
1595 /*! \brief Internal function which returns if the wizard has created the object */
1596 static int sorcery_wizard_create(void *obj, void *arg, int flags)
1597 {
1598         const struct ast_sorcery_object_wizard *object_wizard = obj;
1599         const struct sorcery_details *details = arg;
1600
1601         if (!object_wizard->wizard->create) {
1602                 ast_assert(0);
1603                 ast_log(LOG_ERROR, "Sorcery wizard '%s' doesn't contain a 'create' virtual function.\n",
1604                         object_wizard->wizard->name);
1605                 return 0;
1606         }
1607         return (!object_wizard->caching && !object_wizard->wizard->create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
1608 }
1609
1610 /*! \brief Internal callback function which notifies an individual observer that an object has been created */
1611 static int sorcery_observer_notify_create(void *obj, void *arg, int flags)
1612 {
1613         const struct ast_sorcery_object_type_observer *observer = obj;
1614
1615         if (observer->callbacks->created) {
1616                 observer->callbacks->created(arg);
1617         }
1618
1619         return 0;
1620 }
1621
1622 /*! \brief Internal callback function which notifies observers that an object has been created */
1623 static int sorcery_observers_notify_create(void *data)
1624 {
1625         struct sorcery_observer_invocation *invocation = data;
1626
1627         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_create, invocation->object);
1628         ao2_cleanup(invocation);
1629
1630         return 0;
1631 }
1632
1633 int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
1634 {
1635         const struct ast_sorcery_object_details *details = object;
1636         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1637         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1638         struct sorcery_details sdetails = {
1639                 .sorcery = sorcery,
1640                 .obj = object,
1641         };
1642
1643         if (!object_type) {
1644                 return -1;
1645         }
1646
1647         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_create, &sdetails)) &&
1648                 ao2_container_count(object_type->observers)) {
1649                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1650
1651                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
1652                         ao2_cleanup(invocation);
1653                 }
1654         }
1655
1656         return object_wizard ? 0 : -1;
1657 }
1658
1659 /*! \brief Internal callback function which notifies an individual observer that an object has been updated */
1660 static int sorcery_observer_notify_update(void *obj, void *arg, int flags)
1661 {
1662         const struct ast_sorcery_object_type_observer *observer = obj;
1663
1664         if (observer->callbacks->updated) {
1665                 observer->callbacks->updated(arg);
1666         }
1667
1668         return 0;
1669 }
1670
1671 /*! \brief Internal callback function which notifies observers that an object has been updated */
1672 static int sorcery_observers_notify_update(void *data)
1673 {
1674         struct sorcery_observer_invocation *invocation = data;
1675
1676         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_update, invocation->object);
1677         ao2_cleanup(invocation);
1678
1679         return 0;
1680 }
1681
1682 /*! \brief Internal function which returns if a wizard has updated the object */
1683 static int sorcery_wizard_update(void *obj, void *arg, int flags)
1684 {
1685         const struct ast_sorcery_object_wizard *object_wizard = obj;
1686         const struct sorcery_details *details = arg;
1687
1688         return (object_wizard->wizard->update && !object_wizard->wizard->update(details->sorcery, object_wizard->data, details->obj) &&
1689                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1690 }
1691
1692 int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
1693 {
1694         const struct ast_sorcery_object_details *details = object;
1695         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1696         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1697         struct sorcery_details sdetails = {
1698                 .sorcery = sorcery,
1699                 .obj = object,
1700         };
1701
1702         if (!object_type) {
1703                 return -1;
1704         }
1705
1706         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_update, &sdetails)) &&
1707                 ao2_container_count(object_type->observers)) {
1708                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1709
1710                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
1711                         ao2_cleanup(invocation);
1712                 }
1713         }
1714
1715         return object_wizard ? 0 : -1;
1716 }
1717
1718 /*! \brief Internal callback function which notifies an individual observer that an object has been deleted */
1719 static int sorcery_observer_notify_delete(void *obj, void *arg, int flags)
1720 {
1721         const struct ast_sorcery_object_type_observer *observer = obj;
1722
1723         if (observer->callbacks->deleted) {
1724                 observer->callbacks->deleted(arg);
1725         }
1726
1727         return 0;
1728 }
1729
1730 /*! \brief Internal callback function which notifies observers that an object has been deleted */
1731 static int sorcery_observers_notify_delete(void *data)
1732 {
1733         struct sorcery_observer_invocation *invocation = data;
1734
1735         ao2_callback(invocation->object_type->observers, OBJ_NODATA, sorcery_observer_notify_delete, invocation->object);
1736         ao2_cleanup(invocation);
1737
1738         return 0;
1739 }
1740
1741 /*! \brief Internal function which returns if a wizard has deleted the object */
1742 static int sorcery_wizard_delete(void *obj, void *arg, int flags)
1743 {
1744         const struct ast_sorcery_object_wizard *object_wizard = obj;
1745         const struct sorcery_details *details = arg;
1746
1747         return (object_wizard->wizard->delete && !object_wizard->wizard->delete(details->sorcery, object_wizard->data, details->obj) &&
1748                 !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
1749 }
1750
1751 int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
1752 {
1753         const struct ast_sorcery_object_details *details = object;
1754         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup);
1755         RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup);
1756         struct sorcery_details sdetails = {
1757                 .sorcery = sorcery,
1758                 .obj = object,
1759         };
1760
1761         if (!object_type) {
1762                 return -1;
1763         }
1764
1765         if ((object_wizard = ao2_callback(object_type->wizards, 0, sorcery_wizard_delete, &sdetails)) &&
1766                 ao2_container_count(object_type->observers)) {
1767                 struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
1768
1769                 if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
1770                         ao2_cleanup(invocation);
1771                 }
1772         }
1773
1774         return object_wizard ? 0 : -1;
1775 }
1776
1777 void ast_sorcery_unref(struct ast_sorcery *sorcery)
1778 {
1779         if (sorcery) {
1780                 /* One ref for what we just released, the other for the instances container. */
1781                 ao2_wrlock(instances);
1782                 if (ao2_ref(sorcery, -1) == 2) {
1783                         ao2_unlink_flags(instances, sorcery, OBJ_NOLOCK);
1784                 }
1785                 ao2_unlock(instances);
1786         }
1787 }
1788
1789 const char *ast_sorcery_object_get_id(const void *object)
1790 {
1791         const struct ast_sorcery_object_details *details = object;
1792         return details->object->id;
1793 }
1794
1795 const char *ast_sorcery_object_get_type(const void *object)
1796 {
1797         const struct ast_sorcery_object_details *details = object;
1798         return details->object->type;
1799 }
1800
1801 const char *ast_sorcery_object_get_extended(const void *object, const char *name)
1802 {
1803         const struct ast_sorcery_object_details *details = object;
1804         struct ast_variable *field;
1805
1806         for (field = details->object->extended; field; field = field->next) {
1807                 if (!strcmp(field->name + 1, name)) {
1808                         return field->value;
1809                 }
1810         }
1811
1812         return NULL;
1813 }
1814
1815 int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value)
1816 {
1817         RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy);
1818         struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL;
1819         const struct ast_sorcery_object_details *details = object;
1820
1821         if (!extended) {
1822                 return -1;
1823         }
1824
1825         for (field = details->object->extended; field; previous = field, field = field->next) {
1826                 if (!strcmp(field->name, name)) {
1827                         if (previous) {
1828                                 previous->next = field->next;
1829                         } else {
1830                                 details->object->extended = field->next;
1831                         }
1832                         field->next = NULL;
1833                         break;
1834                 }
1835         }
1836
1837         extended->next = details->object->extended;
1838         details->object->extended = extended;
1839
1840         return 0;
1841 }
1842
1843 int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1844 {
1845         RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
1846         struct ast_sorcery_object_type_observer *observer;
1847         int res;
1848
1849         if (!object_type || !callbacks) {
1850                 return -1;
1851         }
1852
1853         if (!(observer = ao2_alloc(sizeof(*observer), NULL))) {
1854                 return -1;
1855         }
1856
1857         observer->callbacks = callbacks;
1858         res = 0;
1859         if (!ao2_link(object_type->observers, observer)) {
1860                 res = -1;
1861         }
1862         ao2_ref(observer, -1);
1863
1864         return res;
1865 }
1866
1867 /*! \brief Internal callback function for removing an observer */
1868 static int sorcery_observer_remove(void *obj, void *arg, int flags)
1869 {
1870         const struct ast_sorcery_object_type_observer *observer = obj;
1871
1872         return (observer->callbacks == arg) ? CMP_MATCH | CMP_STOP : 0;
1873 }
1874
1875 void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks)
1876 {
1877         RAII_VAR(struct ast_sorcery_object_type *, object_type, NULL, ao2_cleanup);
1878         struct ast_sorcery_observer *cbs = (struct ast_sorcery_observer *) callbacks;/* Remove const for traversal. */
1879
1880         if (!sorcery) {
1881                 return;
1882         }
1883         object_type = ao2_find(sorcery->types, type, OBJ_KEY);
1884         if (!object_type) {
1885                 return;
1886         }
1887
1888         ao2_callback(object_type->observers, OBJ_NODATA | OBJ_UNLINK,
1889                 sorcery_observer_remove, cbs);
1890 }
1891
1892 int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags)
1893 {
1894         const char *right_key = arg;
1895         int cmp;
1896
1897         switch (flags & OBJ_SEARCH_MASK) {
1898         case OBJ_SEARCH_OBJECT:
1899                 right_key = ast_sorcery_object_get_id(arg);
1900                 /* Fall through */
1901         case OBJ_SEARCH_KEY:
1902                 cmp = strcmp(ast_sorcery_object_get_id(obj), right_key);
1903                 break;
1904         case OBJ_SEARCH_PARTIAL_KEY:
1905                 cmp = strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key));
1906                 break;
1907         default:
1908                 cmp = 0;
1909                 break;
1910         }
1911         return cmp;
1912 }
1913
1914 int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
1915 {
1916         const char *right_key = arg;
1917         int cmp = 0;
1918
1919         switch (flags & OBJ_SEARCH_MASK) {
1920         case OBJ_SEARCH_OBJECT:
1921                 right_key = ast_sorcery_object_get_id(arg);
1922                 /* Fall through */
1923         case OBJ_SEARCH_KEY:
1924                 if (strcmp(ast_sorcery_object_get_id(obj), right_key) == 0) {
1925                         cmp = CMP_MATCH | CMP_STOP;
1926                 }
1927                 break;
1928         case OBJ_SEARCH_PARTIAL_KEY:
1929                 if (strncmp(ast_sorcery_object_get_id(obj), right_key, strlen(right_key)) == 0) {
1930                         cmp = CMP_MATCH;
1931                 }
1932                 break;
1933         default:
1934                 cmp = 0;
1935                 break;
1936         }
1937         return cmp;
1938 }
1939
1940 int ast_sorcery_object_id_hash(const void *obj, int flags) {
1941         if (flags & OBJ_SEARCH_OBJECT) {
1942                 return ast_str_hash(ast_sorcery_object_get_id(obj));
1943         } else if (flags & OBJ_SEARCH_KEY) {
1944                 return ast_str_hash(obj);
1945         }
1946         return -1;
1947 }
1948
1949 struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
1950                 const char *type)
1951 {
1952         return ao2_find(sorcery->types, type, OBJ_SEARCH_KEY);
1953 }
1954
1955 static int is_registered_cb(void *obj, void *arg, int flags)
1956 {
1957         struct ast_sorcery_object_field *object_field = obj;
1958         char *name = arg;
1959         int rc = 0;
1960
1961         if (object_field->name_regex
1962                 && !regexec(object_field->name_regex, name, 0, NULL, 0)) {
1963                 rc = CMP_MATCH | CMP_STOP;
1964         }
1965
1966         return rc;
1967 }
1968
1969 int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
1970                 const char *field_name)
1971 {
1972         struct ast_sorcery_object_field *object_field;
1973         int res = 1;
1974
1975         ast_assert(object_type != NULL);
1976
1977         object_field = ao2_find(object_type->fields, field_name, OBJ_SEARCH_KEY);
1978
1979         if (!object_field) {
1980                 object_field = ao2_callback(object_type->fields, 0, is_registered_cb, (char *)field_name);
1981         }
1982
1983         if (!object_field) {
1984                 res = 0;
1985         }
1986
1987         ao2_cleanup(object_field);
1988         return res;
1989 }