Asterisk - The Open Source Telephony Project GIT-master-7e7a603
res_sorcery_config.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/*!
20 * \file
21 *
22 * \brief Sorcery Configuration File Object Wizard
23 *
24 * \author Joshua Colp <jcolp@digium.com>
25 */
26
27/*** MODULEINFO
28 <support_level>core</support_level>
29 ***/
30
31#include "asterisk.h"
32
33#include <regex.h>
34
35#include "asterisk/module.h"
36#include "asterisk/sorcery.h"
37#include "asterisk/astobj2.h"
38#include "asterisk/config.h"
39#include "asterisk/uuid.h"
40#include "asterisk/hashtab.h"
41
42/*! \brief Structure for storing configuration file sourced objects */
44 /*! \brief UUID for identifying us when opening a configuration file */
46
47 /*! \brief Objects retrieved from the configuration file */
49
50 /*! \brief Any specific variable criteria for considering a defined category for this object */
52
53 /*! \brief An explicit name for the configuration section, with it there can be only one */
55
56 /*! \brief Number of buckets to use for objects */
57 unsigned int buckets;
58
59 /*! \brief Enable file level integrity instead of object level */
60 unsigned int file_integrity:1;
61
62 /*! \brief Enable enforcement of a single configuration object of this type */
63 unsigned int single_object:1;
64
65 /*! \brief Configuration is invalid in some way, force reload */
66 unsigned int configuration_invalid:1;
67
68 /*! \brief Configuration contains at least one object with dynamic contents */
69 unsigned int has_dynamic_contents:1;
70
71 /*! \brief Filename of the configuration file */
72 char filename[];
73};
74
75/*! \brief Structure used for fields comparison */
77 /*! \brief Pointer to the sorcery structure */
78 const struct ast_sorcery *sorcery;
79
80 /*! \brief Pointer to the fields to check */
81 const struct ast_variable *fields;
82
83 /*! \brief Regular expression for checking object id */
84 regex_t *regex;
85
86 /*! \brief Prefix for matching object id */
87 const char *prefix;
88
89 /*! \brief Prefix length in bytes for matching object id */
90 const size_t prefix_len;
91
92 /*! \brief Optional container to put object into */
94};
95
96static void *sorcery_config_open(const char *data);
97static void sorcery_config_load(void *data, const struct ast_sorcery *sorcery, const char *type);
98static void sorcery_config_reload(void *data, const struct ast_sorcery *sorcery, const char *type);
99static void *sorcery_config_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id);
100static void *sorcery_config_retrieve_fields(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields);
101static void sorcery_config_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects,
102 const struct ast_variable *fields);
103static void sorcery_config_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
104static void sorcery_config_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len);
105static void sorcery_config_close(void *data);
106
108 .name = "config",
109 .open = sorcery_config_open,
110 .load = sorcery_config_load,
111 .reload = sorcery_config_reload,
112 .force_reload = sorcery_config_load,
113 .retrieve_id = sorcery_config_retrieve_id,
114 .retrieve_fields = sorcery_config_retrieve_fields,
115 .retrieve_multiple = sorcery_config_retrieve_multiple,
116 .retrieve_regex = sorcery_config_retrieve_regex,
117 .retrieve_prefix = sorcery_config_retrieve_prefix,
118 .close = sorcery_config_close,
119};
120
121/*! \brief Destructor function for sorcery config */
122static void sorcery_config_destructor(void *obj)
123{
124 struct sorcery_config *config = obj;
125
127 ast_rwlock_destroy(&config->objects.lock);
128 ast_variables_destroy(config->criteria);
129 ast_free(config->explicit_name);
130}
131
132static int sorcery_config_fields_cmp(void *obj, void *arg, int flags)
133{
134 const struct sorcery_config_fields_cmp_params *params = arg;
136
137 if (params->regex) {
138 /* If a regular expression has been provided see if it matches, otherwise move on */
139 if (!regexec(params->regex, ast_sorcery_object_get_id(obj), 0, NULL, 0)) {
140 ao2_link(params->container, obj);
141 }
142 return 0;
143 } else if (params->prefix) {
144 if (!strncmp(params->prefix, ast_sorcery_object_get_id(obj), params->prefix_len)) {
145 ao2_link(params->container, obj);
146 }
147 return 0;
148 } else if (params->fields &&
149 (!(objset = ast_sorcery_objectset_create(params->sorcery, obj)) ||
150 (!ast_variable_lists_match(objset, params->fields, 0)))) {
151 /* If we can't turn the object into an object set OR if differences exist between the fields
152 * passed in and what are present on the object they are not a match.
153 */
154 return 0;
155 }
156
157 /* We want this object */
158 if (params->container) {
159 /*
160 * We are putting the found objects into the given container instead
161 * of the normal container traversal return mechanism.
162 */
163 ao2_link(params->container, obj);
164 return 0;
165 } else {
166 return CMP_MATCH;
167 }
168}
169
170static void *sorcery_config_retrieve_fields(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields)
171{
172 struct sorcery_config *config = data;
174 struct sorcery_config_fields_cmp_params params = {
175 .sorcery = sorcery,
176 .fields = fields,
177 .container = NULL,
178 };
179
180 /* If no fields are present return nothing, we require *something*, same goes if no objects exist yet */
181 if (!objects || !fields) {
182 return NULL;
183 }
184
185 return ao2_callback(objects, 0, sorcery_config_fields_cmp, &params);
186}
187
188static void *sorcery_config_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
189{
190 struct sorcery_config *config = data;
192
193 return objects ? ao2_find(objects, id, OBJ_SEARCH_KEY) : NULL;
194}
195
196static void sorcery_config_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
197{
198 struct sorcery_config *config = data;
199 RAII_VAR(struct ao2_container *, config_objects, ao2_global_obj_ref(config->objects), ao2_cleanup);
200 struct sorcery_config_fields_cmp_params params = {
201 .sorcery = sorcery,
202 .fields = fields,
203 .container = objects,
204 };
205
206 if (!config_objects) {
207 return;
208 }
209
211}
212
213static void sorcery_config_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex)
214{
215 struct sorcery_config *config = data;
216 RAII_VAR(struct ao2_container *, config_objects, ao2_global_obj_ref(config->objects), ao2_cleanup);
217 regex_t expression;
218 struct sorcery_config_fields_cmp_params params = {
219 .sorcery = sorcery,
220 .container = objects,
221 .regex = &expression,
222 };
223
224 if (ast_strlen_zero(regex)) {
225 regex = ".";
226 }
227
228 if (!config_objects || regcomp(&expression, regex, REG_EXTENDED | REG_NOSUB)) {
229 return;
230 }
231
233 regfree(&expression);
234}
235
236static void sorcery_config_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
237{
238 struct sorcery_config *config = data;
239 RAII_VAR(struct ao2_container *, config_objects, ao2_global_obj_ref(config->objects), ao2_cleanup);
240 struct sorcery_config_fields_cmp_params params = {
241 .sorcery = sorcery,
242 .container = objects,
243 .prefix = prefix,
244 .prefix_len = prefix_len,
245 };
246
247 if (!config_objects) {
248 return;
249 }
250
252}
253
254/*! \brief Internal function which determines if a category matches based on explicit name */
255static int sorcery_is_explicit_name_met(const struct ast_sorcery *sorcery, const char *type,
256 struct ast_category *category, struct sorcery_config *config)
257{
258 struct ast_sorcery_object_type *object_type;
259 struct ast_variable *field;
260 int met = 1;
261
262 if (ast_strlen_zero(config->explicit_name) || strcmp(ast_category_get_name(category), config->explicit_name)) {
263 return 0;
264 }
265
267 if (!object_type) {
268 return 0;
269 }
270
271 /* We iterate the configured fields to see if we don't know any, if we don't then
272 * this is likely not for the given type and we skip it. If it actually is then criteria
273 * may pick it up in which case it would just get rejected as an invalid configuration later.
274 */
275 for (field = ast_category_first(category); field; field = field->next) {
276 if (!ast_sorcery_is_object_field_registered(object_type, field->name)) {
277 met = 0;
278 break;
279 }
280 }
281
282 ao2_ref(object_type, -1);
283
284 return met;
285}
286
287/*! \brief Internal function which determines if a category matches based on criteria */
288static int sorcery_is_criteria_met(struct ast_category *category, struct sorcery_config *config)
289{
291
292 if (!config->criteria) {
293 return 0;
294 }
295
296 return (!ast_sorcery_changeset_create(ast_category_first(category), config->criteria, &diff) && !diff) ? 1 : 0;
297}
298
299/*! \brief Internal function which determines if criteria has been met for considering an object set applicable */
300static int sorcery_is_configuration_met(const struct ast_sorcery *sorcery, const char *type,
301 struct ast_category *category, struct sorcery_config *config)
302{
303 if (!config->criteria && ast_strlen_zero(config->explicit_name)) {
304 /* Nothing is configured to allow specific matching, so accept it! */
305 return 1;
306 } else if (sorcery_is_explicit_name_met(sorcery, type, category, config)) {
307 return 1;
308 } else if (sorcery_is_criteria_met(category, config)) {
309 return 1;
310 } else {
311 /* Nothing explicitly matched so reject */
312 return 0;
313 }
314}
315
316static void sorcery_config_internal_load(void *data, const struct ast_sorcery *sorcery, const char *type, unsigned int reload)
317{
318 struct sorcery_config *config = data;
319 struct ast_flags flags = { reload && !config->configuration_invalid && !config->has_dynamic_contents ? CONFIG_FLAG_FILEUNCHANGED : 0 };
320 struct ast_config *cfg = ast_config_load2(config->filename, config->uuid, flags);
321 struct ast_category *category = NULL;
322 RAII_VAR(struct ao2_container *, objects, NULL, ao2_cleanup);
323 const char *id = NULL;
324 unsigned int buckets = 0;
325 unsigned int has_dynamic_contents = 0;
326
327 if (!cfg) {
328 ast_log(LOG_ERROR, "Unable to load config file '%s'\n", config->filename);
329 return;
330 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
331 ast_debug(1, "Config file '%s' was unchanged\n", config->filename);
332 return;
333 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
334 ast_log(LOG_ERROR, "Contents of config file '%s' are invalid and cannot be parsed\n", config->filename);
335 return;
336 }
337
338 /* When parsing the configuration assume it is valid until proven otherwise */
339 config->configuration_invalid = 0;
340
341 if (!config->buckets) {
342 while ((category = ast_category_browse_filtered(cfg, NULL, category, NULL))) {
343
344 /* If given configuration has not been met skip the category, it is not applicable */
346 continue;
347 }
348
349 buckets++;
350 }
351
352 /* Determine the optimal number of buckets */
353 while (buckets && !ast_is_prime(buckets)) {
354 /* This purposely goes backwards to ensure that the container doesn't have a ton of
355 * empty buckets for objects that will never get added.
356 */
357 buckets--;
358 }
359
360 if (!buckets) {
361 buckets = 1;
362 }
363 } else {
364 buckets = config->buckets;
365 }
366
367 /* For single object configurations there can only ever be one bucket, if there's more than the single
368 * object requirement has been violated.
369 */
370 if (config->single_object && buckets > 1) {
371 ast_log(LOG_ERROR, "Config file '%s' could not be loaded; configuration contains more than one object of type '%s'\n",
372 config->filename, type);
374 config->configuration_invalid = 1;
375 return;
376 }
377
378 ast_debug(2, "Using bucket size of '%d' for objects of type '%s' from '%s'\n",
379 buckets, type, config->filename);
380
383 if (!objects) {
384 ast_log(LOG_ERROR, "Could not create bucket for new objects from '%s', keeping existing objects\n",
385 config->filename);
387 config->configuration_invalid = 1; /* Not strictly invalid but we want to try next time */
388 return;
389 }
390
391 while ((category = ast_category_browse_filtered(cfg, NULL, category, NULL))) {
392 RAII_VAR(void *, obj, NULL, ao2_cleanup);
393 id = ast_category_get_name(category);
394
395 /* If given configuration has not been met skip the category, it is not applicable */
397 continue;
398 }
399
400 /* Confirm an object with this id does not already exist in the bucket.
401 * If it exists, however, the configuration is invalid so stop
402 * processing and destroy it. */
403 obj = ao2_find(objects, id, OBJ_SEARCH_KEY);
404 if (obj) {
405 ast_log(LOG_ERROR, "Config file '%s' could not be loaded; configuration contains a duplicate object: '%s' of type '%s'\n",
406 config->filename, id, type);
408 config->configuration_invalid = 1;
409 return;
410 }
411
412 if (!(obj = ast_sorcery_alloc(sorcery, type, id)) ||
414
415 if (config->file_integrity) {
416 ast_log(LOG_ERROR, "Config file '%s' could not be loaded due to error with object '%s' of type '%s'\n",
417 config->filename, id, type);
419 config->configuration_invalid = 1;
420 return;
421 } else {
422 ast_log(LOG_ERROR, "Could not create an object of type '%s' with id '%s' from configuration file '%s'\n",
423 type, id, config->filename);
424 config->configuration_invalid = 1;
425 }
426
427 ao2_cleanup(obj);
428
429 /* To ensure we don't lose the object that already exists we retrieve it from the old objects container and add it to the new one */
430 if (!(obj = sorcery_config_retrieve_id(sorcery, data, type, id))) {
431 continue;
432 }
433
434 ast_log(LOG_NOTICE, "Retaining existing configuration for object of type '%s' with id '%s'\n", type, id);
435 }
436
437 /* We store the dynamic contents state until the end in case this reload or load
438 * gets rolled back.
439 */
440 has_dynamic_contents |= ast_sorcery_object_has_dynamic_contents(obj);
441
442 ao2_link(objects, obj);
443 }
444
445 config->has_dynamic_contents = has_dynamic_contents;
446 ao2_global_obj_replace_unref(config->objects, objects);
448}
449
450static void sorcery_config_load(void *data, const struct ast_sorcery *sorcery, const char *type)
451{
453}
454
455static void sorcery_config_reload(void *data, const struct ast_sorcery *sorcery, const char *type)
456{
458}
459
460static void *sorcery_config_open(const char *data)
461{
462 char *tmp;
463 char *filename;
464 char *option;
465 struct sorcery_config *config;
466
467 if (ast_strlen_zero(data)) {
468 return NULL;
469 }
470
471 tmp = ast_strdupa(data);
472 filename = strsep(&tmp, ",");
473
475 return NULL;
476 }
477
478 ast_uuid_generate_str(config->uuid, sizeof(config->uuid));
479
480 ast_rwlock_init(&config->objects.lock);
481 strcpy(config->filename, filename);
482
483 while ((option = strsep(&tmp, ","))) {
484 char *name = strsep(&option, "="), *value = option;
485
486 if (!strcasecmp(name, "buckets")) {
487 if (sscanf(value, "%30u", &config->buckets) != 1) {
488 ast_log(LOG_ERROR, "Unsupported bucket size of '%s' used for configuration file '%s', defaulting to automatic determination\n",
489 value, filename);
490 }
491 } else if (!strcasecmp(name, "integrity")) {
492 if (!strcasecmp(value, "file")) {
493 config->file_integrity = 1;
494 } else if (!strcasecmp(value, "object")) {
495 config->file_integrity = 0;
496 } else {
497 ast_log(LOG_ERROR, "Unsupported integrity value of '%s' used for configuration file '%s', defaulting to 'object'\n",
498 value, filename);
499 }
500 } else if (!strcasecmp(name, "criteria")) {
501 char *field = strsep(&value, "=");
502 struct ast_variable *criteria = ast_variable_new(field, value, "");
503
504 if (criteria) {
505 criteria->next = config->criteria;
506 config->criteria = criteria;
507 } else {
508 /* This is fatal since not following criteria would potentially yield invalid objects */
509 ast_log(LOG_ERROR, "Could not create criteria entry of field '%s' with value '%s' for configuration file '%s'\n",
510 field, value, filename);
511 ao2_ref(config, -1);
512 return NULL;
513 }
514 } else if (!strcasecmp(name, "explicit_name")) {
515 ast_free(config->explicit_name);
516 config->explicit_name = ast_strdup(value);
517 if (ast_strlen_zero(config->explicit_name)) {
518 /* This is fatal since it could stop a configuration section from getting applied */
519 ast_log(LOG_ERROR, "Could not create explicit name entry of '%s' for configuration file '%s'\n",
520 value, filename);
521 ao2_ref(config, -1);
522 return NULL;
523 }
524 } else if (!strcasecmp(name, "single_object")) {
525 if (ast_strlen_zero(value)) {
526 ast_log(LOG_ERROR, "Could not set single object value for configuration file '%s' as the value is empty\n",
527 filename);
528 ao2_ref(config, -1);
529 return NULL;
530 }
531 config->single_object = ast_true(value);
532 } else {
533 ast_log(LOG_ERROR, "Unsupported option '%s' used for configuration file '%s'\n", name, filename);
534 }
535 }
536
537 return config;
538}
539
540static void sorcery_config_close(void *data)
541{
542 struct sorcery_config *config = data;
543
544 ao2_ref(config, -1);
545}
546
547static int load_module(void)
548{
551 }
552
554}
555
556static int unload_module(void)
557{
559 return 0;
560}
561
562AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Sorcery Configuration File Object Wizard",
563 .support_level = AST_MODULE_SUPPORT_CORE,
564 .load = load_module,
565 .unload = unload_module,
566 .load_pri = AST_MODPRI_REALTIME_DRIVER,
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
Definition: astobj2.h:901
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
Definition: astobj2.h:918
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:404
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Definition: astobj2.h:859
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_MULTIPLE
Definition: astobj2.h:1049
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
Definition: astobj2.h:1101
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
static int tmp()
Definition: bt_open.c:389
static const char type[]
Definition: chan_ooh323.c:109
static const char config[]
Definition: chan_ooh323.c:111
static const char name[]
Definition: format_mp3.c:68
static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
int ast_is_prime(int num)
Determines if the specified number is prime.
Definition: hashtab.c:101
static char prefix[MAX_PREFIX]
Definition: http.c:144
char * strsep(char **str, const char *delims)
Configuration File Parser.
const char * ast_category_get_name(const struct ast_category *category)
Return the name of the category.
Definition: main/config.c:1117
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:3321
#define ast_variable_new(name, value, filename)
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_category_first(struct ast_category *cat)
given a pointer to a category, return the root variable.
Definition: main/config.c:1246
int ast_variable_lists_match(const struct ast_variable *left, const struct ast_variable *right, int exact_match)
Tests 2 variable lists to see if they match.
Definition: main/config.c:861
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
@ CONFIG_FLAG_FILEUNCHANGED
struct ast_category * ast_category_browse_filtered(struct ast_config *config, const char *category_name, struct ast_category *prev, const char *filter)
Browse categories with filters.
Definition: main/config.c:1424
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:233
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:317
@ AST_MODFLAG_GLOBAL_SYMBOLS
Definition: module.h:316
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:543
@ AST_MODPRI_REALTIME_DRIVER
Definition: module.h:323
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static int reload(void)
static struct ast_sorcery * sorcery
static int sorcery_is_criteria_met(struct ast_category *category, struct sorcery_config *config)
Internal function which determines if a category matches based on criteria.
static void * sorcery_config_retrieve_id(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id)
static struct ast_sorcery_wizard config_object_wizard
static int sorcery_is_configuration_met(const struct ast_sorcery *sorcery, const char *type, struct ast_category *category, struct sorcery_config *config)
Internal function which determines if criteria has been met for considering an object set applicable.
static void sorcery_config_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
static void sorcery_config_close(void *data)
static void sorcery_config_reload(void *data, const struct ast_sorcery *sorcery, const char *type)
static int sorcery_is_explicit_name_met(const struct ast_sorcery *sorcery, const char *type, struct ast_category *category, struct sorcery_config *config)
Internal function which determines if a category matches based on explicit name.
static void sorcery_config_internal_load(void *data, const struct ast_sorcery *sorcery, const char *type, unsigned int reload)
static int load_module(void)
static int unload_module(void)
static void * sorcery_config_open(const char *data)
static void sorcery_config_load(void *data, const struct ast_sorcery *sorcery, const char *type)
static void sorcery_config_destructor(void *obj)
Destructor function for sorcery config.
static void * sorcery_config_retrieve_fields(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields)
static void sorcery_config_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields)
static int sorcery_config_fields_cmp(void *obj, void *arg, int flags)
static void sorcery_config_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex)
#define NULL
Definition: resample.c:96
Sorcery Data Access Layer API.
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface)
Unregister a sorcery wizard.
Definition: sorcery.c:474
#define ast_sorcery_objectset_create(sorcery, object)
Create an object set (KVP list) for an object.
Definition: sorcery.h:1137
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:2494
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags)
ao2 object comparator based on sorcery id.
Definition: sorcery.c:2464
unsigned int ast_sorcery_object_has_dynamic_contents(const void *object)
Get whether an object contains dynamic contents or not.
Definition: sorcery.c:2377
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
#define ast_sorcery_wizard_register(interface)
See __ast_sorcery_wizard_register()
Definition: sorcery.h:383
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:2514
void * ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id)
Allocate an object.
Definition: sorcery.c:1744
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
int ast_sorcery_object_id_hash(const void *obj, int flags)
ao2 object hasher based on sorcery id.
Definition: sorcery.c:2475
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Generic container type.
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Structure for registered object type.
Definition: sorcery.c:148
Interface for a sorcery wizard.
Definition: sorcery.h:276
const char * name
Name of the wizard.
Definition: sorcery.h:278
Full structure for sorcery.
Definition: sorcery.c:230
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Structure used for fields comparison.
const char * prefix
Prefix for matching object id.
struct ao2_container * container
Optional container to put object into.
const size_t prefix_len
Prefix length in bytes for matching object id.
const struct ast_sorcery * sorcery
Pointer to the sorcery structure.
const struct ast_variable * fields
Pointer to the fields to check.
regex_t * regex
Regular expression for checking object id.
Structure for storing configuration file sourced objects.
unsigned int has_dynamic_contents
Configuration contains at least one object with dynamic contents.
char uuid[AST_UUID_STR_LEN]
UUID for identifying us when opening a configuration file.
unsigned int single_object
Enable enforcement of a single configuration object of this type.
struct ao2_global_obj objects
Objects retrieved from the configuration file.
unsigned int configuration_invalid
Configuration is invalid in some way, force reload.
char filename[]
Filename of the configuration file.
struct ast_variable * criteria
Any specific variable criteria for considering a defined category for this object.
char * explicit_name
An explicit name for the configuration section, with it there can be only one.
unsigned int file_integrity
Enable file level integrity instead of object level.
unsigned int buckets
Number of buckets to use for objects.
int value
Definition: syslog.c:37
#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:941
Universally unique identifier support.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141