asterisk/include/asterisk/sorcery.h

1631 lines
58 KiB
C
Raw Normal View History

/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
*
* Joshua Colp <jcolp@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
* \brief Sorcery Data Access Layer API
* \author Joshua Colp <jcolp@digium.com>
* \ref AstSorcery
*/
/*!
* \page AstSorcery Data Access Layer API
*
* Sorcery is a unifying data access layer which utilizes the configuration framework,
* realtime, and astdb to allow object creation, retrieval, updating, and deletion.
*
* \par Initialization
*
* Usage of sorcery is accomplished by first opening a sorcery structure. This structure holds
* all information about the object types, object fields, and object mappings. All API functions
* require the sorcery structure to operate. When sorcery is no longer needed the structure can
* be unreferenced using \ref ast_sorcery_unref
*
* Once opened the sorcery structure must have object mappings applied to it. This maps the
* object types to their respective wizards (object storage modules). If the developer would like
* to allow the user to configure this using the sorcery.conf configuration file the
* \ref ast_sorcery_apply_config API call can be used to read in the configuration file and apply the
* mappings. \ref ast_sorcery_open will automatically call \ref ast_sorcery_apply_config to allow
* for configuration of objects using the same category name as the module that is opening the
* sorcery instance. Direct calls to \ref ast_sorcery_apply_config should only be performed if a
* module wishes to allow for additional configuration sections in sorcery.conf to be used.
* If the storage of the object types are such that a default wizard can be used this can
* be applied using the \ref ast_sorcery_apply_default API call. Note that the default mappings will not
* override configured mappings. They are only used in the case where no configured mapping exists.
*
* Configuring object mappings implicitly creates a basic version of an object type. The object type
* must be fully registered, however, using the \ref ast_sorcery_object_register API call before any
* objects of the type can be allocated, created, or retrieved.
*
* Once the object type itself has been fully registered the individual fields within the object must
* be registered using the \ref ast_sorcery_object_field_register API call. Note that not all fields *need*
* be registered. Only fields that should be accessible using the sorcery API have to be registered.
*
* \par Creating Objects
*
* Before an object can be created within the sorcery API it must first be allocated using the
* \ref ast_sorcery_alloc API call. This allocates a new instance of the object, sets sorcery specific
* details, and applies default values to the object. A unique identifier can optionally be specified
* when allocating an object. If it is not provided one will be automatically generated. Allocating
* an object does not create it within any object storage mechanisms that are configured for the
* object type. Creation must explicitly be done using the \ref ast_sorcery_create API call. This API call
* passes the object to each configured object storage mechanism for the object type until one
* successfully persists the object.
*
* \par Retrieving Objects
*
* To retrieve a single object using its unique identifier the \ref ast_sorcery_retrieve_by_id API call
* can be used.
*
* To retrieve potentially multiple objects using specific fields the \ref ast_sorcery_retrieve_by_fields
* API call can be used. The behavior of this API call is controlled using different flags. If the
* AST_RETRIEVE_FLAG_MULTIPLE flag is used a container will be returned which contains all matching objects.
* To retrieve all objects the AST_RETRIEVE_FLAG_ALL flag can be specified. Note that when specifying this flag
* you do not need to pass any fields.
*
* Both API calls return shared objects. Modification of the object can not occur until it has been copied.
*
* \par Updating Objects
*
* As retrieved objects may be shared the first step to updating the object with new details is creating a
* copy using the \ref ast_sorcery_copy API call. This will return a new object which is specific to the caller.
* Any field within the object may be modified as needed. Once changes are done the changes can be committed
* using the \ref ast_sorcery_update API call. Note that as the copied object is specific to the caller it must
* be unreferenced after use.
*
* \par Deleting Objects
*
* To delete an object simply call the \ref ast_sorcery_delete API call with an object retrieved using the
* ast_sorcery_retrieve_by_* API calls or a copy returned from \ref ast_sorcery_copy.
*/
#ifndef _ASTERISK_SORCERY_H
#define _ASTERISK_SORCERY_H
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
#include "asterisk/config_options.h"
#include "asterisk/uuid.h"
/*! \brief Maximum size of an object type */
#define MAX_OBJECT_TYPE 64
res_pjsip: AMI commands and events. Created the following AMI commands and corresponding events for res_pjsip: PJSIPShowEndpoints - Provides a listing of all pjsip endpoints and a few select attributes on each. Events: EndpointList - for each endpoint a few attributes. EndpointlistComplete - after all endpoints have been listed. PJSIPShowEndpoint - Provides a detail list of attributes for a specified endpoint. Events: EndpointDetail - attributes on an endpoint. AorDetail - raised for each AOR on an endpoint. AuthDetail - raised for each associated inbound and outbound auth TransportDetail - transport attributes. IdentifyDetail - attributes for the identify object associated with the endpoint. EndpointDetailComplete - last event raised after all detail events. PJSIPShowRegistrationsInbound - Provides a detail listing of all inbound registrations. Events: InboundRegistrationDetail - inbound registration attributes for each registration. InboundRegistrationDetailComplete - raised after all detail records have been listed. PJSIPShowRegistrationsOutbound - Provides a detail listing of all outbound registrations. Events: OutboundRegistrationDetail - outbound registration attributes for each registration. OutboundRegistrationDetailComplete - raised after all detail records have been listed. PJSIPShowSubscriptionsInbound - A detail listing of all inbound subscriptions and their attributes. Events: SubscriptionDetail - on each subscription detailed attributes SubscriptionDetailComplete - raised after all detail records have been listed. PJSIPShowSubscriptionsOutbound - A detail listing of all outboundbound subscriptions and their attributes. Events: SubscriptionDetail - on each subscription detailed attributes SubscriptionDetailComplete - raised after all detail records have been listed. (issue ASTERISK-22609) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2959/ ........ Merged revisions 403131 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403133 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-11-23 17:26:57 +00:00
/*! \brief Maximum length of an object field name */
#define MAX_OBJECT_FIELD 128
/*!
* \brief Retrieval flags
*/
enum ast_sorcery_retrieve_flags {
/*! \brief Default retrieval flags */
AST_RETRIEVE_FLAG_DEFAULT = 0,
/*! \brief Return all matching objects */
AST_RETRIEVE_FLAG_MULTIPLE = (1 << 0),
/*! \brief Perform no matching, return all objects */
AST_RETRIEVE_FLAG_ALL = (1 << 1),
};
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
/*!
* \brief Field handler flags
*/
enum ast_sorcery_field_handler_flags {
/*! \brief Try both handlers, string first */
AST_HANDLER_PREFER_STRING,
/*! \brief Try both handlers, list first */
AST_HANDLER_PREFER_LIST,
/*! \brief Use string handler only */
AST_HANDLER_ONLY_STRING,
/*! \brief Use list handler only */
AST_HANDLER_ONLY_LIST,
};
/*! \brief Forward declaration for the sorcery main structure and wizard structure */
struct ast_sorcery;
struct ast_sorcery_wizard;
/*!
* \brief A callback function for translating a value into a string
*
* \param obj Object to get value from
* \param args Where the field is
* \param buf Pointer to the buffer that the handler has created which contains the field value
*
* \retval 0 success
* \retval -1 failure
*/
typedef int (*sorcery_field_handler)(const void *obj, const intptr_t *args, char **buf);
/*!
* \brief A callback function for translating multiple values into an ast_variable list
*
* \param obj Object to get values from
* \param fields Pointer to store the list of fields
*
* \retval 0 success
* \retval -1 failure
*/
typedef int (*sorcery_fields_handler)(const void *obj, struct ast_variable **fields);
/*!
* \brief A callback function for performing a transformation on an object set
*
* \param set The existing object set
*
* \retval non-NULL new object set if changed
* \retval NULL if no changes present
*
* \note The returned ast_variable list must be *new*. You can not return the input set.
*/
typedef struct ast_variable *(*sorcery_transform_handler)(struct ast_variable *set);
/*!
* \brief A callback function for when an object set is successfully applied to an object
*
* \note On a failure return, the state of the object is left undefined. It is a bad
* idea to try to use this object.
*
* \param sorcery Sorcery structure in use
* \param obj The object itself
* \retval 0 Success
* \retval non-zero Failure
*/
typedef int (*sorcery_apply_handler)(const struct ast_sorcery *sorcery, void *obj);
/*!
* \brief A callback function for copying the contents of one object to another
*
* \param src The source object
* \param dst The destination object
*
* \retval 0 success
* \retval -1 failure
*/
typedef int (*sorcery_copy_handler)(const void *src, void *dst);
/*!
* \brief A callback function for generating a changeset between two objects
*
* \param original The original object
* \param modified The modified object
* \param changes The changeset
*
* \retval 0 success
* \retval -1 failure
*/
typedef int (*sorcery_diff_handler)(const void *original, const void *modified, struct ast_variable **changes);
/*! \brief Interface for the global sorcery observer */
struct ast_sorcery_global_observer {
/*! \brief Callback after an instance is created */
void (*instance_created)(const char *name, struct ast_sorcery *sorcery);
/*! \brief Callback after an wizard is registered */
void (*wizard_registered)(const char *name,
const struct ast_sorcery_wizard *wizard);
/*! \brief Callback before an instance is destroyed */
void (*instance_destroying)(const char *name, struct ast_sorcery *sorcery);
/*! \brief Callback before a wizard is unregistered */
void (*wizard_unregistering)(const char *name,
const struct ast_sorcery_wizard *wizard);
};
/*! \brief Interface for the sorcery instance observer */
struct ast_sorcery_instance_observer {
/*! \brief Callback before instance is loaded/reloaded */
void (*instance_loading)(const char *name, const struct ast_sorcery *sorcery,
int reloaded);
/*! \brief Callback after instance is loaded/reloaded */
void (*instance_loaded)(const char *name, const struct ast_sorcery *sorcery,
int reloaded);
/*! \brief Callback after a wizard is mapped to an object_type */
void (*wizard_mapped)(const char *name, struct ast_sorcery *sorcery,
const char *object_type, struct ast_sorcery_wizard *wizard,
const char *wizard_args, void *wizard_data);
/*! \brief Callback after any object_type is registered */
void (*object_type_registered)(const char *name, struct ast_sorcery *sorcery,
const char *object_type);
/*! \brief Callback before any object_type is loaded/reloaded */
void (*object_type_loading)(const char *name, const struct ast_sorcery *sorcery,
const char *object_type, int reloaded);
/*! \brief Callback after any object_type is loaded/reloaded */
void (*object_type_loaded)(const char *name, const struct ast_sorcery *sorcery,
const char *object_type, int reloaded);
};
/*! \brief Interface for the sorcery wizard observer */
struct ast_sorcery_wizard_observer {
/*! \brief Callback before a wizard is loaded/reloaded for any type */
void (*wizard_loading)(const char *name, const struct ast_sorcery_wizard *wizard,
const char *object_type, int reloaded);
/*! \brief Callback after a wizard is loaded/reloaded for any type */
void (*wizard_loaded)(const char *name, const struct ast_sorcery_wizard *wizard,
const char *object_type, int reloaded);
};
/*! \brief Interface for a sorcery wizard */
struct ast_sorcery_wizard {
/*! \brief Name of the wizard */
const char *name;
/*! \brief Pointer to the Asterisk module this wizard is implemented by */
struct ast_module *module;
/*! \brief Callback for opening a wizard */
void *(*open)(const char *data);
/*! \brief Optional callback for loading persistent objects */
void (*load)(void *data, const struct ast_sorcery *sorcery, const char *type);
/*! \brief Optional callback for reloading persistent objects */
void (*reload)(void *data, const struct ast_sorcery *sorcery, const char *type);
/*! \brief Callback for creating an object */
int (*create)(const struct ast_sorcery *sorcery, void *data, void *object);
/*! \brief Callback for retrieving an object using an id */
void *(*retrieve_id)(const struct ast_sorcery *sorcery, void *data, const char *type, const char *id);
/*! \brief Callback for retrieving multiple objects using a regex on their id */
void (*retrieve_regex)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
/*! \brief Optional callback for retrieving multiple objects by matching their id with a prefix */
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);
/*! \brief Optional callback for retrieving an object using fields */
void *(*retrieve_fields)(const struct ast_sorcery *sorcery, void *data, const char *type, const struct ast_variable *fields);
/*! \brief Optional callback for retrieving multiple objects using some optional field criteria */
void (*retrieve_multiple)(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const struct ast_variable *fields);
/*! \brief Callback for updating an object */
int (*update)(const struct ast_sorcery *sorcery, void *data, void *object);
/*! \brief Callback for deleting an object */
int (*delete)(const struct ast_sorcery *sorcery, void *data, void *object);
/*! \brief Callback for closing a wizard */
void (*close)(void *data);
/*! \brief Callback for whether or not the wizard believes the object is stale */
int (*is_stale)(const struct ast_sorcery *sorcery, void *data, void *object);
/*! \brief Optional callback for forcing a reload to occur, even if wizard has determined no changes */
void (*force_reload)(void *data, const struct ast_sorcery *sorcery, const char *type);
};
/*! \brief Interface for a sorcery object type observer */
struct ast_sorcery_observer {
/*! \brief Callback for when an object is created */
void (*created)(const void *object);
/*! \brief Callback for when an object is updated */
void (*updated)(const void *object);
/*! \brief Callback for when an object is deleted */
void (*deleted)(const void *object);
/*! \brief Callback for when an object type is loaded/reloaded */
void (*loaded)(const char *object_type);
};
/*! \brief Opaque structure for internal sorcery object */
struct ast_sorcery_object;
/*! \brief Structure which contains details about a sorcery object */
struct ast_sorcery_object_details {
/*! \brief Pointer to internal sorcery object information */
struct ast_sorcery_object *object;
};
/*! \brief Macro which must be used at the beginning of each sorcery capable object */
#define SORCERY_OBJECT(details) \
struct { \
struct ast_sorcery_object_details details; \
} \
/*!
* \brief Initialize the sorcery API
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_init(void);
/*!
* \brief Register a sorcery wizard
*
* \param interface Pointer to a wizard interface
* \param module Pointer to the module implementing the interface
*
* \retval 0 success
* \retval -1 failure
*/
int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module);
/*!
* \brief See \ref __ast_sorcery_wizard_register()
*/
#define ast_sorcery_wizard_register(interface) __ast_sorcery_wizard_register(interface, AST_MODULE_SELF)
/*!
* \brief Unregister a sorcery wizard
*
* \param interface Pointer to the wizard interface
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_wizard_unregister(const struct ast_sorcery_wizard *interface);
/*!
* \brief Open a new sorcery structure
*
* \param module The module name (AST_MODULE)
*
* When called, this will automatically also call __ast_sorcery_apply_config()
* with the module name as the configuration section.
*
* \retval non-NULL success
* \retval NULL if allocation failed
*/
#define ast_sorcery_open() __ast_sorcery_open(AST_MODULE, __FILE__, __LINE__, __PRETTY_FUNCTION__)
struct ast_sorcery *__ast_sorcery_open(const char *module, const char *file, int line, const char *func);
/*!
* \brief Retrieves an existing sorcery instance by module name
*
* \param module_name The module name
*
* \retval non-NULL success
* \retval NULL if no instance was found
*
* \note The returned instance has its reference count incremented. The caller
* must decrement the count when they're finished with it.
*
*/
struct ast_sorcery *ast_sorcery_retrieve_by_module_name(const char *module_name);
enum ast_sorcery_apply_result {
/*! Sorcery wizard failed to apply. */
AST_SORCERY_APPLY_FAIL = -1,
/*! Sorcery wizard applied successfully. */
AST_SORCERY_APPLY_SUCCESS = 0,
/*! Sorcery wizard has already been applied to the object type. */
AST_SORCERY_APPLY_DUPLICATE = 1,
/*! Default sorcery wizard is unnecessary since a wizard has already been applied to the object type. */
AST_SORCERY_APPLY_DEFAULT_UNNECESSARY = 2,
/*! No sorcery.conf configuration file was found to apply. */
AST_SORCERY_APPLY_NO_CONFIGURATION = 3,
};
/*!
* \brief Apply configured wizard mappings
*
* \param sorcery Pointer to a sorcery structure
* \param name Name of the category to use within the configuration file, normally the module name
* \param module The module name (AST_MODULE)
*
* This function is called automatically by __ast_sorcery_open() using the module name as the
* configuration category. The only reason you should call this function is if your module
* wishes to apply configuration from additional sections of sorcery.conf.
*
* If a configuration section attempts to apply the same sorcery wizard to an object type
* more than once, the wizard will only be applied one time.
*
* \return What happened when attempting to apply the config.
*/
enum ast_sorcery_apply_result __ast_sorcery_apply_config(struct ast_sorcery *sorcery,
const char *name, const char *module);
#define ast_sorcery_apply_config(sorcery, name) \
__ast_sorcery_apply_config((sorcery), (name), AST_MODULE)
/*!
* \brief Apply default object wizard mappings
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to apply to
* \param module The name of the module, typically AST_MODULE
* \param name Name of the wizard to use
* \param data Data to be passed to wizard
*
* \return What occurred when applying the default
*
* \note This should be called *after* applying configuration sourced mappings
*
* \note Only a single default can exist per object type
*/
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);
#define ast_sorcery_apply_default(sorcery, type, name, data) \
__ast_sorcery_apply_default((sorcery), (type), AST_MODULE, (name), (data))
/*!
* \brief Apply additional object wizard mappings
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to apply to
* \param module The name of the module, typically AST_MODULE
* \param name Name of the wizard to use
* \param data Data to be passed to wizard
* \param caching Wizard should cache
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
*/
enum ast_sorcery_apply_result __ast_sorcery_apply_wizard_mapping(struct ast_sorcery *sorcery,
const char *type, const char *module, const char *name, const char *data, unsigned int caching);
/*!
* \brief Apply additional object wizard mappings
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to apply to
* \param name Name of the wizard to use
* \param data Data to be passed to wizard
* \param caching Wizard should cache
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
*/
#define ast_sorcery_apply_wizard_mapping(sorcery, type, name, data, caching) \
__ast_sorcery_apply_wizard_mapping((sorcery), (type), AST_MODULE, (name), (data), (caching));
/*!
* \brief Pre-defined locations to insert at
*/
enum ast_sorcery_wizard_position {
AST_SORCERY_WIZARD_POSITION_LAST = -1,
AST_SORCERY_WIZARD_POSITION_FIRST = 0,
};
/*!
* \brief Insert an additional object wizard mapping at a specific position
* in the wizard list
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to apply to
* \param module The name of the module, typically AST_MODULE
* \param name Name of the wizard to use
* \param data Data to be passed to wizard
* \param caching Wizard should cache
* \param position An index to insert to or one of ast_sorcery_wizard_position
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
* \note Wizards can be retrieved by using ast_sorcery_get_wizard_mapping_count
* and iterating over them using ast_sorcery_get_wizard_mapping.
*
* \since 13.4.0
*/
enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sorcery *sorcery,
const char *type, const char *module, const char *name, const char *data,
unsigned int caching, int position);
/*!
* \brief Insert an additional object wizard mapping at a specific position
* in the wizard list
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to apply to
* \param name Name of the wizard to use
* \param data Data to be passed to wizard
* \param caching Wizard should cache
* \param position One of ast_sorcery_wizard_position
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
* \since 13.4.0
*/
#define ast_sorcery_insert_wizard_mapping(sorcery, type, name, data, caching, position) \
__ast_sorcery_insert_wizard_mapping((sorcery), (type), AST_MODULE, (name), (data), \
(caching), (position))
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
/*!
* \brief Wizard Apply Flags
*
* These flags apply only to a wizard/object-type combination.
* The same wizard may be applied to a different object-type with
* different flags and behavior. If ALLOW_DUPLICATE is set
* the wizard could even be applied to the same object-type
* with different flags.
*/
enum ast_sorcery_wizard_apply_flags {
/*! Apply no special behavior */
AST_SORCERY_WIZARD_APPLY_NONE = (0 << 0),
/*! This wizard will cache this object type's entries */
AST_SORCERY_WIZARD_APPLY_CACHING = (1 << 0),
/*! This wizard won't allow Create, Update or Delete operations on this object type */
AST_SORCERY_WIZARD_APPLY_READONLY = (1 << 1),
/*! This wizard will allow other instances of itself on the same object type */
AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE = (1 << 2)
};
/*!
* \brief Insert an additional object wizard mapping at a specific position
* in the wizard list returning wizard information
* \since 13.26.0
* \since 16.3.0
*
* \param sorcery Pointer to a sorcery structure
* \param object_type_name Name of the object type to apply to
* \param module The name of the module, typically AST_MODULE
* \param wizard_type_name Name of the wizard type to use
* \param wizard_args Opaque string to be passed to the wizard
* May be NULL but see note below
* \param flags One or more of enum ast_sorcery_wizard_apply_flags
* \param position An index to insert to or one of ast_sorcery_wizard_position
* \param[out] wizard A variable to receive a pointer to the ast_sorcery_wizard structure.
* May be NULL if not needed.
* \param[out] wizard_data A variable to receive a pointer to the wizard's internal data.
* May be NULL if not needed.
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
*
* \note Although \p wizard_args is an optional parameter it is highly
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* recommended to supply one. If you use the AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE
* flag, and you intend to ever remove a wizard mapping, you'll need \p wizard_args
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* to remove specific instances of a wizard type.
*/
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);
/*!
* \brief Insert an additional object wizard mapping at a specific position
* in the wizard list returning wizard information
* \since 13.26.0
* \since 16.3.0
*
* \param sorcery Pointer to a sorcery structure
* \param object_type_name Name of the object type to apply to
* \param wizard_type_name Name of the wizard type to use
* \param wizard_args Opaque string to be passed to the wizard
* May be NULL but see note below
* \param flags One or more of enum ast_sorcery_wizard_apply_flags
* \param position An index to insert to or one of ast_sorcery_wizard_position
* \param[out] wizard A variable to receive a pointer to the ast_sorcery_wizard structure.
* May be NULL if not needed.
* \param[out] wizard_data A variable to receive a pointer to the wizard's internal data.
* May be NULL if not needed.
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
*
* \note Although \p wizard_args is an optional parameter it is highly
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* recommended to supply one. If you use the AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE
* flag, and you intend to ever remove a wizard mapping, you'll need \p wizard_args
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* to remove specific instances.
*/
#define ast_sorcery_object_type_insert_wizard(sorcery, \
object_type_name, wizard_type_name, wizard_args, flags, \
position, wizard, wizard_data) \
__ast_sorcery_object_type_insert_wizard((sorcery), \
(object_type_name), AST_MODULE, (wizard_type_name), (wizard_args), (flags), \
position, (wizard), (wizard_data))
/*!
* \brief Apply additional object wizard mappings returning wizard information
* \since 13.26.0
* \since 16.3.0
*
* \param sorcery Pointer to a sorcery structure
* \param object_type_name Name of the object type to apply to
* \param wizard_type_name Name of the wizard type to use
* \param wizard_args Opaque string to be passed to the wizard
* May be NULL but see note below
* \param flags One or more of enum ast_sorcery_wizard_apply_flags
* \param[out] wizard A variable to receive a pointer to the ast_sorcery_wizard structure.
* May be NULL if not needed.
* \param[out] wizard_data A variable to receive a pointer to the wizard's internal data.
* May be NULL if not needed.
*
* \return What occurred when applying the mapping
*
* \note This should be called *after* applying default mappings
*
* \note Although \p wizard_args is an optional parameter it is highly
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* recommended to supply one. If you use the AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE
* flag, and you intend to ever remove a wizard mapping, you'll need \p wizard_args
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* to remove specific instances.
*/
#define ast_sorcery_object_type_apply_wizard(sorcery, \
object_type_name, wizard_type_name, wizard_args, flags, \
wizard, wizard_data) \
__ast_sorcery_object_type_insert_wizard((sorcery), \
(object_type_name), AST_MODULE, (wizard_type_name), (wizard_args), (flags), \
AST_SORCERY_WIZARD_POSITION_LAST, (wizard), (wizard_data))
/*!
* \brief Remove an object wizard mapping
* \since 13.26.0
* \since 16.3.0
*
* \param sorcery Pointer to a sorcery structure
* \param object_type_name Name of the object type to remove from
* \param module The name of the module, typically AST_MODULE
* \param wizard_type_name The name of the of the wizard type to remove
* \param wizard_args Opaque string originally passed to the wizard
*
* \retval 0 success
* \retval -1 failure
*
* \note If there were multiple instances of the same wizard type
* added to this object type without using \p wizard_args, then
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* only the first wizard matching wizard_type will be removed.
*/
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);
/*!
* \brief Remove an object wizard mapping
* \since 13.26.0
* \since 16.3.0
*
* \param sorcery Pointer to a sorcery structure
* \param object_type_name Name of the object type to remove from
* \param wizard_type_name The name of the of the wizard type to remove
* \param wizard_args Opaque string originally passed to the wizard
*
* \retval 0 success
* \retval -1 failure
*
* \note If there were multiple instances of the same wizard type
* added to this object type without using \p wizard_args, then
sorcery.c: Sorcery enhancements for wizard management Added ability to specifiy a wizard is read-only when applying it to a specific object type. This allows you to specify create, update and delete callbacks for the wizard but limit which object types can use them. Added the ability to allow an object type to have multiple wizards of the same type. This is indicated when a wizard is added to a specific object type. Added 3 new sorcery wizard functions: * ast_sorcery_object_type_insert_wizard which does the same thing as the existing ast_sorcery_insert_wizard_mapping function but accepts the new read-only and allot-duplicates flags and also returns the ast_sorcery_wizard structure used and it's internal data structure. This allows immediate use of the wizard's callbacks without having to register a "wizard mapped" observer. * ast_sorcery_object_type_apply_wizard which does the same thing as the existing ast_sorcery_apply_wizard_mapping function but has the added capabilities of ast_sorcery_object_type_insert_wizard. * ast_sorcery_object_type_remove_wizard which removes a wizard matching both its name and its original argument string. * The original logic in __ast_sorcery_insert_wizard_mapping was moved to __ast_sorcery_object_type_insert_wizard and enhanced for the new capabilities, then __ast_sorcery_insert_wizard_mapping was refactored to just call __ast_sorcery_insert_wizard_mapping. * Added a unit test to test_sorcery.c to test the read-only capability. Change-Id: I40f35840252e4313d99e11dbd80e270a3aa10605
2019-03-14 16:46:53 +00:00
* only the first wizard matching wizard_type will be removed.
*/
#define ast_sorcery_object_type_remove_wizard(sorcery, object_type_name, \
wizard_type_name, wizard_args) \
__ast_sorcery_object_type_remove_wizard((sorcery), (object_type_name), \
AST_MODULE, (wizard_type_name), (wizard_args))
/*!
* \brief Remove an object wizard mapping
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to remove from
* \param module The name of the module, typically AST_MODULE
* \param name The name of the wizard to remove
*
* \retval 0 success
* \retval -1 failure
*
* \since 13.4.0
*/
int __ast_sorcery_remove_wizard_mapping(struct ast_sorcery *sorcery,
const char *type, const char *module, const char *name);
/*!
* \brief Remove an object wizard mapping
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to remove from
* \param name The name of the wizard to remove
*
* \retval 0 success
* \retval -1 failure
*
* \since 13.4.0
*/
#define ast_sorcery_remove_wizard_mapping(sorcery, type, name) \
__ast_sorcery_remove_wizard_mapping((sorcery), (type), AST_MODULE, (name))
/*!
* \brief Return the number of wizards mapped to an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
*
* \return Number of wizards or -1 for error
* \since 13.4.0
*/
int ast_sorcery_get_wizard_mapping_count(struct ast_sorcery *sorcery,
const char *type);
/*!
* \brief By index, return a wizard mapped to an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param index Index of the wizard
* \param wizard A pointer to receive the wizard pointer
* \param data A pointer to receive the data pointer
*
* \retval 0 success
* \retval -1 failure
*
* \warning The wizard will have its reference count bumped so you must
* call ao2_cleanup when you're done with it.
*
* \note The wizard and data returned are valid only for this object type
* and only while the wizard is applied to the object type.
*
* \since 13.4.0
*/
int ast_sorcery_get_wizard_mapping(struct ast_sorcery *sorcery,
const char *type, int index, struct ast_sorcery_wizard **wizard, void **data);
/*!
* \brief Unregister an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_object_unregister(struct ast_sorcery *sorcery, const char *type);
/*!
* \brief Register an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param hidden All objects of this type are internal and should not be manipulated by users
* \param reloadable All objects of this type are reloadable
* \param alloc Required object allocation callback
* \param transform Optional transformation callback
* \param apply Optional object set apply callback
*
* \note In general, this function should not be used directly. One of the various
* macro'd versions should be used instead.
*
* \retval 0 success
* \retval -1 failure
*/
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);
/*!
* \brief Register an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param alloc Required object allocation callback
* \param transform Optional transformation callback
* \param apply Optional object set apply callback
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply) \
__ast_sorcery_object_register((sorcery), (type), 0, 1, (alloc), (transform), (apply))
/*!
* \brief Register an object type that is not reloadable
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param alloc Required object allocation callback
* \param transform Optional transformation callback
* \param apply Optional object set apply callback
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_register_no_reload(sorcery, type, alloc, transform, apply) \
__ast_sorcery_object_register((sorcery), (type), 0, 0, (alloc), (transform), (apply))
/*!
* \brief Register an internal, hidden object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param alloc Required object allocation callback
* \param transform Optional transformation callback
* \param apply Optional object set apply callback
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_internal_object_register(sorcery, type, alloc, transform, apply) \
__ast_sorcery_object_register((sorcery), (type), 1, 1, (alloc), (transform), (apply))
/*!
* \brief Set the high and low alert water marks of the sorcery object type.
* \since 13.10.0
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param low_water New queue low water mark. (-1 to set as 90% of high_water)
* \param high_water New queue high water mark.
*
* \retval 0 on success.
* \retval -1 on error (water marks not changed).
*/
int ast_sorcery_object_set_congestion_levels(struct ast_sorcery *sorcery, const char *type, long low_water, long high_water);
/*!
* \brief Set the copy handler for an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param copy Copy handler
*/
void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy);
/*!
* \brief Set the diff handler for an object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param diff Diff handler
*/
void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff);
/*!
* \brief Register a regex for multiple fields within an object
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param regex A regular expression pattern for the fields
* \param config_handler A custom handler for translating the string representation of the fields
* \param sorcery_handler A custom handler for translating the native representation of the fields
*
* \retval 0 success
* \retval -1 failure
*/
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);
/*!
* \brief Register a field within an object
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
* \param config_handler A custom handler for translating the string representation of the fields
* \param sorcery_handler A custom handler for translating the native representation of the fields
* \param multiple_handler A custom handler for translating the native representation of the fields
* \param opt_type Option type
* \param flags Option type specific flags
* \param no_doc Field should not be documented
* \param alias Interpret and apply field value only
* \param argc
*
* \retval 0 success
* \retval -1 failure
*/
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
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, ...);
/*!
* \brief Register a field within an object
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param opt_type Option type
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, NULL, NULL, NULL, flags, 0, 0, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
/*!
* \brief Register a field within an object as an alias
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param opt_type Option type
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_field_register_alias(sorcery, type, name, default_val, opt_type, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, NULL, NULL, NULL, flags, 1, 1, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
/*!
* \brief Register a field within an object without documentation
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param opt_type Option type
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, opt_type, NULL, NULL, NULL, flags, 1, 0, VA_NARGS(__VA_ARGS__), __VA_ARGS__)
/*!
* \brief Register a field within an object with custom handlers
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param config_handler Custom configuration handler
* \param sorcery_handler Custom sorcery handler
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
* \param multiple_handler Custom multiple handler
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
#define ast_sorcery_object_field_register_custom(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, OPT_CUSTOM_T, config_handler, sorcery_handler, multiple_handler, flags, 0, 0, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
/*!
* \brief Register a field within an object with custom handlers as an alias
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param config_handler Custom configuration handler
* \param sorcery_handler Custom sorcery handler
* \param multiple_handler Custom multiple handler
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
#define ast_sorcery_object_field_register_custom_alias(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, OPT_CUSTOM_T, config_handler, sorcery_handler, multiple_handler, flags, 1, 1, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
/*!
* \brief Register a field within an object with custom handlers without documentation
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object
* \param name Name of the field
* \param default_val Default value of the field
* \param config_handler Custom configuration handler
* \param sorcery_handler Custom sorcery handler
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
* \param multiple_handler Custom multiple handler
* \param flags Option type specific flags
*
* \retval 0 success
* \retval -1 failure
*/
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
#define ast_sorcery_object_field_register_custom_nodoc(sorcery, type, name, default_val, config_handler, sorcery_handler, multiple_handler, flags, ...) \
__ast_sorcery_object_field_register(sorcery, type, name, default_val, OPT_CUSTOM_T, config_handler, sorcery_handler, multiple_handler, flags, 1, 0, VA_NARGS(__VA_ARGS__), __VA_ARGS__);
/*!
* \brief Inform any wizards to load persistent objects
*
* \param sorcery Pointer to a sorcery structure
*/
void ast_sorcery_load(const struct ast_sorcery *sorcery);
/*!
* \brief Inform any wizards of a specific object type to load persistent objects
*
* \param sorcery Pointer to a sorcery structure
* \param type Name of the object type to load
*/
void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type);
/*!
* \brief Inform any wizards to reload persistent objects
*
* \param sorcery Pointer to a sorcery structure
*/
void ast_sorcery_reload(const struct ast_sorcery *sorcery);
/*!
* \brief Inform any wizards to reload persistent objects, even if no changes determined
*
* \param sorcery Pointer to a sorcery structure
*
* \since 13.32.0
* \since 16.9.0
* \since 17.3.0
*/
void ast_sorcery_force_reload(const struct ast_sorcery *sorcery);
/*!
* \brief Inform any wizards of a specific object type to reload persistent objects
*
* \param sorcery Pointer to a sorcery structure
* \param type Name of the object type to reload
*/
void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type);
/*!
* \brief Inform any wizards of a specific object type to reload persistent objects
* even if no changes determined
*
* \param sorcery Pointer to a sorcery structure
* \param type Name of the object type to reload
*
* \since 13.32.0
* \since 16.9.0
* \since 17.3.0
*/
void ast_sorcery_force_reload_object(const struct ast_sorcery *sorcery, const char *type);
/*!
* \brief Increase the reference count of a sorcery structure
*
* \param sorcery Pointer to a sorcery structure
*/
void ast_sorcery_ref(struct ast_sorcery *sorcery);
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
/*!
* \brief Create an object set (KVP list) for an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
* \param flags Flags indicating which handler to use and in what order.
*
* \retval non-NULL success
* \retval NULL if error occurred
*
* \note The returned ast_variable list must be destroyed using ast_variables_destroy
*/
struct ast_variable *ast_sorcery_objectset_create2(const struct ast_sorcery *sorcery,
const void *object, enum ast_sorcery_field_handler_flags flags);
/*!
* \brief Create an object set (KVP list) for an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
*
* \retval non-NULL success
* \retval NULL if error occurred
*
* \note The returned ast_variable list must be destroyed using ast_variables_destroy
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
*
* \note This function attempts to use a field's sorcery_fields_handler first and if that
* doesn't exist or fails, a field's sorcery_field_handler is used. The difference is
* that the former may return multiple list entries for the same field and the latter will only
* return 1. It's up to the field itself to determine what the appropriate content is.
*/
sorcery: Create AST_SORCERY dialplan function. This patch creates the AST_SORCERY dialplan function which allows someone to retrieve any value from a sorcery-based config file. It's similar to AST_CONFIG. The creation of the function itself was fairly straightforward but it required changes to the underlying sorcery infrastructure that rippled into individual sorcery objects. The changes stemmed from inconsistencies in how sorcery created ast_variable objectsets from sorcery objects and the inconsistency in how individual objects used that feature especially when it came to parameters that can be specified multiple times like contact in aor and match in identify. You can read more here... http://lists.digium.com/pipermail/asterisk-dev/2014-February/065202.html So, what this patch does, besides actually creating the AST_SORCERY function, is the following... * Creates ast_variable_list_append which is a helper to append one ast_variable list to another. * Modifies the ast_sorcery_object_field_register functions to accept the already-defined sorcery_fields_handler callback. * Modifies ast_sorcery_objectset_create to accept a parameter indicating return type preference...a single ast_variable with all values concatenated or an ast_variable list with multiple entries. Also fixed a few bugs. * Modifies individual sorcery object implementations to use the new function definition of the ast_sorcery_object_field_register functions. * Modifies location.c and res_pjsip_endpoint_identifier_ip.c to implement sorcery_fields_handler handlers so they return multiple occurrences as an ast_variable_list. * Added a whole bunch of tests to test_sorcery. (closes issue ASTERISK-22537) Review: http://reviewboard.asterisk.org/r/3254/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410042 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-03-06 22:39:54 +00:00
#define ast_sorcery_objectset_create(sorcery, object) \
ast_sorcery_objectset_create2(sorcery, object, AST_HANDLER_PREFER_LIST)
/*!
* \brief Create an object set in JSON format for an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
*
* \retval non-NULL success
* \retval NULL if error occurred
*
* \note The returned ast_json object must be unreferenced using ast_json_unref
*/
struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object);
/*!
* \brief Apply an object set (KVP list) to an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
* \param objectset Object set itself
*
* \retval 0 success
* \retval -1 failure
*
* \note This operation is *not* atomic. If this fails it is possible for the object to be left with a partially
* applied object set.
*/
int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset);
/*!
* \brief Create a changeset given two object sets
*
* \param original Original object set
* \param modified Modified object set
* \param changes Pointer to hold any changes between the object sets
*
* \retval 0 success
* \retval -1 failure
*
* \note The returned ast_variable list must be destroyed using ast_variables_destroy
*/
int ast_sorcery_changeset_create(const struct ast_variable *original, const struct ast_variable *modified, struct ast_variable **changes);
/*!
* \brief Allocate a generic sorcery capable object
*
* \param size Size of the object
* \param destructor Optional destructor function
*
* \retval non-NULL success
* \retval NULL failure
*
* \note The returned object does not support AO2 locking.
*/
void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor);
/*!
* \since 14.1.0
* \brief Allocate a generic sorcery capable object with locking.
*
* \details Sorcery objects may be replaced with new allocations during reloads.
* If locking is required on sorcery objects it must be shared between the old
* object and the new one. lockobj can be any AO2 object with locking enabled,
* but in most cases named locks should be used to provide stable locking.
*
* \param size Size of the object
* \param destructor Optional destructor function
* \param lockobj An AO2 object that will provide locking.
*
* \retval non-NULL success
* \retval NULL failure
*/
void *ast_sorcery_lockable_alloc(size_t size, ao2_destructor_fn destructor, void *lockobj);
/*!
* \brief Allocate an object
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to allocate
* \param id Optional unique identifier, if none is provided one will be generated
*
* \retval non-NULL success
* \retval NULL failure
*/
void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id);
/*!
* \brief Create a copy of an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Existing object
*
* \retval non-NULL success
* \retval NULL failure
*/
void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object);
/*!
* \brief Create a changeset of two objects
*
* \param sorcery Pointer to a sorcery structure
* \param original Original object
* \param modified Modified object
* \param changes Pointer which will be populated with changes if any exist
*
* \retval 0 success
* \retval -1 failure
*
* \note The returned ast_variable list must be destroyed using ast_variables_destroy
*
* \note While the objects must be of the same type they do not have to be the same object
*/
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes);
/*!
* \brief Add a global observer to sorcery
*
* \param callbacks Implementation of the global observer interface
*
* \retval 0 success
* \retval -1 failure
*
* \note You must be ready to accept observer invocations before this function is called
*/
int ast_sorcery_global_observer_add(const struct ast_sorcery_global_observer *callbacks);
/*!
* \brief Remove a global observer from sorcery.
*
* A global observer is notified...
* After a new wizard is registered.
* After a new sorcery instance is opened.
* Before an instance is destroyed.
* Before a wizard is unregistered.
*
* \param callbacks Implementation of the global observer interface
*/
void ast_sorcery_global_observer_remove(const struct ast_sorcery_global_observer *callbacks);
/*!
* \brief Add an observer to a sorcery instance
*
* \param sorcery Pointer to a sorcery structure
* \param callbacks Implementation of the instance observer interface
*
* An instance observer is notified...
* Before an instance is loaded or reloaded.
* After an instance is loaded or reloaded.
* After a wizard is mapped to an object type.
* After an object type is registered.
* Before an object type is loaded or reloaded.
* After an object type is loaded or reloaded.
*
* \retval 0 success
* \retval -1 failure
*
* \note You must be ready to accept observer invocations before this function is called
*/
int ast_sorcery_instance_observer_add(struct ast_sorcery *sorcery,
const struct ast_sorcery_instance_observer *callbacks);
/*!
* \brief Remove an observer from a sorcery instance
*
* \param sorcery Pointer to a sorcery structure
* \param callbacks Implementation of the instance observer interface
*/
void ast_sorcery_instance_observer_remove(struct ast_sorcery *sorcery,
const struct ast_sorcery_instance_observer *callbacks);
/*!
* \brief Add an observer to a sorcery wizard
*
* \param wizard Pointer to a previously registered wizard structure
* \param callbacks Implementation of the wizard observer interface
*
* A wizard observer is notified...
* Before a wizard is loaded or reloaded.
* After a wizard is loaded or reloaded.
*
* \retval 0 success
* \retval -1 failure
*
* \note You must be ready to accept observer invocations before this function is called
*/
int ast_sorcery_wizard_observer_add(struct ast_sorcery_wizard *wizard,
const struct ast_sorcery_wizard_observer *callbacks);
/*!
* \brief Remove an observer from a sorcery wizard.
*
* \param interface Pointer to a sorcery structure
* \param callbacks Implementation of the wizard observer interface
*/
void ast_sorcery_wizard_observer_remove(struct ast_sorcery_wizard *interface,
const struct ast_sorcery_wizard_observer *callbacks);
/*!
* \brief Add an observer to a specific object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object that should be observed
* \param callbacks Implementation of the observer interface
*
* \retval 0 success
* \retval -1 failure
*
* \note You must be ready to accept observer invocations before this function is called
*/
int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks);
/*!
* \brief Remove an observer from a specific object type
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object that should no longer be observed
* \param callbacks Implementation of the observer interface
*/
void ast_sorcery_observer_remove(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks);
/*!
* \brief Create and potentially persist an object using an available wizard
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object);
/*!
* \brief Retrieve an object using its unique identifier
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to retrieve
* \param id Unique object identifier
*
* \retval non-NULL if found
* \retval NULL if not found
*/
void *ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id);
/*!
* \brief Retrieve an object or multiple objects using specific fields
sorcery/res_pjsip: Refactor for realtime performance There were a number of places in the res_pjsip stack that were getting all endpoints or all aors, and then filtering them locally. A good example is pjsip_options which, on startup, retrieves all endpoints, then the aors for those endpoints, then tests the aors to see if the qualify_frequency is > 0. One issue was that it never did anything with the endpoints other than retrieve the aors so we probably could have skipped a step and just retrieved all aors. But nevermind. This worked reasonably well with local config files but with a realtime backend and thousands of objects, this was a nightmare. The issue really boiled down to the fact that while realtime supports predicates that are passed to the database engine, the non-realtime sorcery backends didn't. They do now. The realtime engines have a scheme for doing simple comparisons. They take in an ast_variable (or list) for matching, and the name of each variable can contain an operator. For instance, a name of "qualify_frequency >" and a value of "0" would create a SQL predicate that looks like "where qualify_frequency > '0'". If there's no operator after the name, the engines add an '=' so a simple name of "qualify_frequency" and a value of "10" would return exact matches. The non-realtime backends decide whether to include an object in a result set by calling ast_sorcery_changeset_create on every object in the internal container. However, ast_sorcery_changeset_create only does exact string matches though so a name of "qualify_frequency >" and a value of "0" returns nothing because the literal "qualify_frequency >" doesn't match any name in the objset set. So, the real task was to create a generic string matcher that can take a left value, operator and a right value and perform the match. To that end, strings.c has a new ast_strings_match(left, operator, right) function. Left and right are the strings to operate on and the operator can be a string containing any of the following: = (or NULL or ""), !=, >, >=, <, <=, like or regex. If the operator is like or regex, the right string should be a %-pattern or a regex expression. If both left and right can be converted to float, then a numeric comparison is performed, otherwise a string comparison is performed. To use this new function on ast_variables, 2 new functions were added to config.c. One that compares 2 ast_variables, and one that compares 2 ast_variable lists. The former is useful when you want to compare 2 ast_variables that happen to be in a list but don't want to traverse the list. The latter will traverse the right list and return true if all the variables in it match the left list. Now, the backends' fields_cmp functions call ast_variable_lists_match instead of ast_sorcery_changeset_create and they can now process the same syntax as the realtime engines. The realtime backend just passes the variable list unaltered to the engine. The only gotcha is that there's no common realtime engine support for regex so that's been noted in the api docs for ast_sorcery_retrieve_by_fields. Only one more change to sorcery was done... A new config flag "allow_unqualified_fetch" was added to reg_sorcery_realtime. "no": ignore fetches if no predicate fields were supplied. "error": same as no but emit an error. (good for testing) "yes": allow (the default); "warn": allow but emit a warning. (good for testing) Now on to res_pjsip... pjsip_options was modified to retrieve aors with qualify_frequency > 0 rather than all endpoints then all aors. Not only was this a big improvement in realtime retrieval but even for config files there's an improvement because we're not going through endpoints anymore. res_pjsip_mwi was modified to retieve only endpoints with something in the mailboxes field instead of all endpoints then testing mailboxes. res_pjsip_registrar_expire was completely refactored. It was retrieving all contacts then setting up scheduler entries to check for expiration. Now, it's a single thread (like keepalive) that periodically retrieves only contacts whose expiration time is < now and deletes them. A new contact_expiration_check_interval was added to global with a default of 30 seconds. Ross Beer reports that with this patch, his Asterisk startup time dropped from around an hour to under 30 seconds. There are still objects that can't be filtered at the database like identifies, transports, and registrations. These are not going to be anywhere near as numerous as endpoints, aors, auths, contacts however. Back to allow_unqualified_fetch. If this is set to yes and you have a very large number of objects in the database, the pjsip CLI commands will attempt to retrive ALL of them if not qualified with a LIKE. Worse, if you type "pjsip show endpoint <tab>" guess what's going to happen? :) Having a cache helps but all the objects will have to be retrieved at least once to fill the cache. Setting allow_unqualified_fetch=no prevents the mass retrieve and should be used on endpoints, auths, aors, and contacts. It should NOT be used for identifies, registrations and transports since these MUST be retrieved in bulk. Example sorcery.conf: [res_pjsip] endpoint=config,pjsip.conf,criteria=type=endpoint endpoint=realtime,ps_endpoints,allow_unqualified_fetch=error ASTERISK-25826 #close Reported-by: Ross Beer Tested-by: Ross Beer Change-Id: Id2691e447db90892890036e663aaf907b2dc1c67
2016-03-08 21:55:30 +00:00
* \since 13.9.0
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to retrieve
* \param flags Flags to control behavior
* \param fields Optional object fields and values to match against
*
* \retval non-NULL if found
* \retval NULL if not found
*
* \note If the AST_RETRIEVE_FLAG_MULTIPLE flag is specified the returned value will be an
* ao2_container that must be unreferenced after use.
*
* \note If the AST_RETRIEVE_FLAG_ALL flag is used you may omit fields to retrieve all objects
* of the given type.
sorcery/res_pjsip: Refactor for realtime performance There were a number of places in the res_pjsip stack that were getting all endpoints or all aors, and then filtering them locally. A good example is pjsip_options which, on startup, retrieves all endpoints, then the aors for those endpoints, then tests the aors to see if the qualify_frequency is > 0. One issue was that it never did anything with the endpoints other than retrieve the aors so we probably could have skipped a step and just retrieved all aors. But nevermind. This worked reasonably well with local config files but with a realtime backend and thousands of objects, this was a nightmare. The issue really boiled down to the fact that while realtime supports predicates that are passed to the database engine, the non-realtime sorcery backends didn't. They do now. The realtime engines have a scheme for doing simple comparisons. They take in an ast_variable (or list) for matching, and the name of each variable can contain an operator. For instance, a name of "qualify_frequency >" and a value of "0" would create a SQL predicate that looks like "where qualify_frequency > '0'". If there's no operator after the name, the engines add an '=' so a simple name of "qualify_frequency" and a value of "10" would return exact matches. The non-realtime backends decide whether to include an object in a result set by calling ast_sorcery_changeset_create on every object in the internal container. However, ast_sorcery_changeset_create only does exact string matches though so a name of "qualify_frequency >" and a value of "0" returns nothing because the literal "qualify_frequency >" doesn't match any name in the objset set. So, the real task was to create a generic string matcher that can take a left value, operator and a right value and perform the match. To that end, strings.c has a new ast_strings_match(left, operator, right) function. Left and right are the strings to operate on and the operator can be a string containing any of the following: = (or NULL or ""), !=, >, >=, <, <=, like or regex. If the operator is like or regex, the right string should be a %-pattern or a regex expression. If both left and right can be converted to float, then a numeric comparison is performed, otherwise a string comparison is performed. To use this new function on ast_variables, 2 new functions were added to config.c. One that compares 2 ast_variables, and one that compares 2 ast_variable lists. The former is useful when you want to compare 2 ast_variables that happen to be in a list but don't want to traverse the list. The latter will traverse the right list and return true if all the variables in it match the left list. Now, the backends' fields_cmp functions call ast_variable_lists_match instead of ast_sorcery_changeset_create and they can now process the same syntax as the realtime engines. The realtime backend just passes the variable list unaltered to the engine. The only gotcha is that there's no common realtime engine support for regex so that's been noted in the api docs for ast_sorcery_retrieve_by_fields. Only one more change to sorcery was done... A new config flag "allow_unqualified_fetch" was added to reg_sorcery_realtime. "no": ignore fetches if no predicate fields were supplied. "error": same as no but emit an error. (good for testing) "yes": allow (the default); "warn": allow but emit a warning. (good for testing) Now on to res_pjsip... pjsip_options was modified to retrieve aors with qualify_frequency > 0 rather than all endpoints then all aors. Not only was this a big improvement in realtime retrieval but even for config files there's an improvement because we're not going through endpoints anymore. res_pjsip_mwi was modified to retieve only endpoints with something in the mailboxes field instead of all endpoints then testing mailboxes. res_pjsip_registrar_expire was completely refactored. It was retrieving all contacts then setting up scheduler entries to check for expiration. Now, it's a single thread (like keepalive) that periodically retrieves only contacts whose expiration time is < now and deletes them. A new contact_expiration_check_interval was added to global with a default of 30 seconds. Ross Beer reports that with this patch, his Asterisk startup time dropped from around an hour to under 30 seconds. There are still objects that can't be filtered at the database like identifies, transports, and registrations. These are not going to be anywhere near as numerous as endpoints, aors, auths, contacts however. Back to allow_unqualified_fetch. If this is set to yes and you have a very large number of objects in the database, the pjsip CLI commands will attempt to retrive ALL of them if not qualified with a LIKE. Worse, if you type "pjsip show endpoint <tab>" guess what's going to happen? :) Having a cache helps but all the objects will have to be retrieved at least once to fill the cache. Setting allow_unqualified_fetch=no prevents the mass retrieve and should be used on endpoints, auths, aors, and contacts. It should NOT be used for identifies, registrations and transports since these MUST be retrieved in bulk. Example sorcery.conf: [res_pjsip] endpoint=config,pjsip.conf,criteria=type=endpoint endpoint=realtime,ps_endpoints,allow_unqualified_fetch=error ASTERISK-25826 #close Reported-by: Ross Beer Tested-by: Ross Beer Change-Id: Id2691e447db90892890036e663aaf907b2dc1c67
2016-03-08 21:55:30 +00:00
*
* \note The fields parameter can contain realtime-style expressions in variable->name.
* All operators defined for ast_strings_match can be used except for regex as
* there's no common support for regex in the realtime backends at this time.
* If multiple variables are in the fields list, all must match for an object to
* be returned. See ast_strings_match for more information.
*
* Example:
*
* The following code can be significantly faster when a realtime backend is in use
* because the expression "qualify_frequency > 0" is passed to the database to limit
* the number of rows returned.
*
* struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", "");
* struct ao2_container *aors;
*
* if (!var) {
* return;
* }
*
* aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
* "aor", AST_RETRIEVE_FLAG_MULTIPLE, var);
*
*/
void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const char *type, unsigned int flags, struct ast_variable *fields);
/*!
* \brief Retrieve multiple objects using a regular expression on their id
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to retrieve
* \param regex Regular expression
*
* \retval non-NULL if error occurs
* \retval NULL success
*
* \note The provided regex is treated as extended case sensitive.
*/
struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex);
/*!
* \brief Retrieve multiple objects whose id begins with the specified prefix
* \since 13.19.0
*
* \param sorcery Pointer to a sorcery structure
* \param type Type of object to retrieve
* \param prefix Object id prefix
* \param prefix_len The length of prefix in bytes
*
* \retval non-NULL if error occurs
* \retval NULL success
*
* \note The prefix is matched in a case sensitive manner.
*/
struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len);
/*!
* \brief Update an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object);
/*!
* \brief Delete an object
*
* \param sorcery Pointer to a sorcery structure
* \param object Pointer to a sorcery object
*
* \retval 0 success
* \retval -1 failure
*/
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object);
/*!
* \brief Determine if a sorcery object is stale with respect to its backing datastore
* \since 14.0.0
*
* This function will query the wizard(s) backing the particular sorcery object to
* determine if the in-memory object is now stale. No action is taken to update
* the object. Callers of this function may use one of the ast_sorcery_retrieve
* functions to obtain a new instance of the object if desired.
*
* \retval 0 the object is not stale
* \retval 1 the object is stale
*/
int ast_sorcery_is_stale(const struct ast_sorcery *sorcery, void *object);
/*!
* \brief Decrease the reference count of a sorcery structure
*
* \param sorcery Pointer to a sorcery structure
*
* \note Prior to 16.0.0 this was a function which had to be used.
* Now you can use any variant of ao2_cleanup or ao2_ref to
* release a reference.
*/
#define ast_sorcery_unref(sorcery) \
ao2_cleanup(sorcery)
/*!
* \brief Get the unique identifier of a sorcery object
*
* \param object Pointer to a sorcery object
*
* \return unique identifier
*/
const char *ast_sorcery_object_get_id(const void *object);
/*!
* \since 14.0.0
* \brief Get when the sorcery object was created
*
* \param object Pointer to a sorcery object
*
* \return The time when the object was created
*/
const struct timeval ast_sorcery_object_get_created(const void *object);
/*!
* \brief Get the type of a sorcery object
*
* \param object Pointer to a sorcery object
*
* \return type of object
*/
const char *ast_sorcery_object_get_type(const void *object);
/*!
* \brief Get an extended field value from a sorcery object
*
* \param object Pointer to a sorcery object
* \param name Name of the extended field value
*
* \retval non-NULL if found
* \retval NULL if not found
*
* \note The returned string does NOT need to be freed and is guaranteed to remain valid for the lifetime of the object
*/
const char *ast_sorcery_object_get_extended(const void *object, const char *name);
/*!
* \brief Set an extended field value on a sorcery object
*
* \param object Pointer to a sorcery object
* \param name Name of the extended field
* \param value Value of the extended field
*
* \retval 0 success
* \retval -1 failure
*
* \note The field name MUST begin with '@' to indicate it is an extended field.
* \note If the extended field already exists it will be overwritten with the new value.
*/
int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value);
/*!
* \brief Get whether an object contains dynamic contents or not
*
* \param object Pointer to a sorcery object
*
* \since 19
* \since 18.3.0
* \since 16.17.0
*/
unsigned int ast_sorcery_object_has_dynamic_contents(const void *object);
/*!
* \brief Set the dynamic contents flag on a sorcery object
*
* \param object Pointer to a sorcery object
*
* \since 19
* \since 18.3.0
* \since 16.17.0
*/
void ast_sorcery_object_set_has_dynamic_contents(const void *object);
/*!
* \brief ao2 object comparator based on sorcery id.
*/
int ast_sorcery_object_id_compare(void *obj, void *arg, int flags);
/*!
* \brief ao2 object sorter based on sorcery id.
*/
int ast_sorcery_object_id_sort(const void *obj, const void *arg, int flags);
/*!
* \brief ao2 object hasher based on sorcery id.
*/
int ast_sorcery_object_id_hash(const void *obj, int flags);
/*!
* \brief Get the sorcery object type given a type name.
*
* \param sorcery The sorcery from which to retrieve the object type
* \param type The type name
*/
struct ast_sorcery_object_type *ast_sorcery_get_object_type(const struct ast_sorcery *sorcery,
const char *type);
/*!
* \brief Determine if a particular object field has been registered with sorcery
*
* \param object_type The object type to check against
* \param field_name The name of the field to check
*
* \retval 0 The field is not registered for this sorcery type
* \retval 1 The field is registered for this sorcery type
*/
int ast_sorcery_is_object_field_registered(const struct ast_sorcery_object_type *object_type,
const char *field_name);
/*!
* \brief Get the module that has opened the provided sorcery instance.
*
* \param sorcery The sorcery instance
*
* \return The module
*/
const char *ast_sorcery_get_module(const struct ast_sorcery *sorcery);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _ASTERISK_SORCERY_H */