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