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