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