@ -109,6 +109,15 @@ struct ast_sorcery_object_wizard {
/*! \brief Wizard is acting as an object cache */
unsigned int caching : 1 ;
/*! \brief Wizard is read_only */
unsigned int read_only : 1 ;
/*! \brief Wizard allows others of the same type */
unsigned int allow_duplicates : 1 ;
/*! \brief Wizard arguments */
char wizard_args [ 0 ] ;
} ;
/*! \brief Interface for a sorcery object type wizards */
@ -802,6 +811,35 @@ int ast_sorcery_get_wizard_mapping(struct ast_sorcery *sorcery,
return 0 ;
}
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 )
{
RAII_VAR ( struct ast_sorcery_object_type * , object_type ,
ao2_find ( sorcery - > types , object_type_name , OBJ_SEARCH_KEY ) , ao2_cleanup ) ;
int res = - 1 ;
int i ;
if ( ! object_type ) {
return res ;
}
AST_VECTOR_RW_WRLOCK ( & object_type - > wizards ) ;
for ( i = 0 ; i < AST_VECTOR_SIZE ( & object_type - > wizards ) ; i + + ) {
struct ast_sorcery_object_wizard * wizard = AST_VECTOR_GET ( & object_type - > wizards , i ) ;
if ( strcmp ( wizard - > wizard - > callbacks . name , wizard_type_name ) = = 0
& & strcmp ( S_OR ( wizard - > wizard_args , " " ) , S_OR ( wizard_args , " " ) ) = = 0 ) {
ao2_cleanup ( AST_VECTOR_REMOVE_ORDERED ( & object_type - > wizards , i ) ) ;
res = 0 ;
break ;
}
}
AST_VECTOR_RW_UNLOCK ( & object_type - > wizards ) ;
return res ;
}
/*! \brief Internal function removes a wizard mapping */
int __ast_sorcery_remove_wizard_mapping ( struct ast_sorcery * sorcery ,
const char * type , const char * module , const char * name )
@ -822,29 +860,35 @@ int __ast_sorcery_remove_wizard_mapping(struct ast_sorcery *sorcery,
return res ;
}
/*! \brief Internal function which creates an object type and inserts a wizard mapping */
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 )
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 )
{
RAII_VAR ( struct ast_sorcery_object_type * , object_type , ao2_find ( sorcery - > types , type, OBJ_KEY ) , ao2_cleanup ) ;
RAII_VAR ( struct ast_sorcery_internal_wizard * , wizard, ao2_find ( wizards , name, OBJ_KEY ) , ao2_cleanup ) ;
RAII_VAR ( struct ast_sorcery_object_wizard * , object_wizard , ao2_alloc ( sizeof ( * object_wizard ) , sorcery_object_wizard_destructor ) , ao2_cleanup ) ;
RAII_VAR ( struct ast_sorcery_object_type * , object_type , ao2_find ( sorcery - > types , object_ type_nam e, OBJ_KEY ) , ao2_cleanup ) ;
RAII_VAR ( struct ast_sorcery_internal_wizard * , internal_ wizard, ao2_find ( wizards , wizard_type_ name, OBJ_KEY ) , ao2_cleanup ) ;
RAII_VAR ( struct ast_sorcery_object_wizard * , object_wizard , NULL , ao2_cleanup ) ;
int created = 0 ;
object_wizard = ao2_alloc ( sizeof ( * object_wizard )
+ ( ast_strlen_zero ( wizard_args ) ? 0 : strlen ( wizard_args ) + 1 ) ,
sorcery_object_wizard_destructor ) ;
if ( ! object_wizard ) {
return AST_SORCERY_APPLY_FAIL ;
}
if ( ! wizard | | wizard - > callbacks . module ! = ast_module_running_ref ( wizard - > callbacks . module ) ) {
ast_log ( LOG_ERROR , " Wizard '%s' could not be applied to object type '%s' as it was not found \n " ,
name , type ) ;
if ( ! internal_wizard
| | internal_wizard - > callbacks . module ! = ast_module_running_ref ( internal_wizard - > callbacks . module ) ) {
ast_log ( LOG_ERROR ,
" Wizard '%s' could not be applied to object type '%s' as it was not found \n " ,
wizard_type_name , object_type_name ) ;
return AST_SORCERY_APPLY_FAIL ;
}
if ( ! object_type ) {
if ( ! ( object_type = sorcery_object_type_alloc ( type, module ) ) ) {
ast_module_unref ( wizard- > callbacks . module ) ;
if ( ! ( object_type = sorcery_object_type_alloc ( object_ type_nam e, module ) ) ) {
ast_module_unref ( internal_ wizard- > callbacks . module ) ;
return AST_SORCERY_APPLY_FAIL ;
}
created = 1 ;
@ -855,29 +899,34 @@ enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sor
struct ast_sorcery_object_wizard * found ;
# define WIZARD_COMPARE(a, b) ((a)->wizard == (b))
found = AST_VECTOR_GET_CMP ( & object_type - > wizards , wizard, WIZARD_COMPARE ) ;
found = AST_VECTOR_GET_CMP ( & object_type - > wizards , internal_ wizard, WIZARD_COMPARE ) ;
# undef WIZARD_COMPARE
if ( found ) {
if ( found
& & ! ( ( flags & AST_SORCERY_WIZARD_APPLY_ALLOW_DUPLICATE ) | | found - > allow_duplicates ) ) {
ast_debug ( 1 , " Wizard %s already applied to object type %s \n " ,
wizard- > callbacks . name , object_type - > name ) ;
internal_ wizard- > callbacks . name , object_type - > name ) ;
AST_VECTOR_RW_UNLOCK ( & object_type - > wizards ) ;
ast_module_unref ( wizard- > callbacks . module ) ;
ast_module_unref ( internal_ wizard- > callbacks . module ) ;
return AST_SORCERY_APPLY_DUPLICATE ;
}
}
ast_debug ( 5 , " Calling wizard %s open callback on object type %s \n " ,
name, object_type - > name ) ;
if ( wizard- > callbacks . open & & ! ( object_wizard - > data = wizard- > callbacks . open ( data ) ) ) {
wizard_type_ name, object_type - > name ) ;
if ( internal_ wizard- > callbacks . open & & ! ( object_wizard - > data = internal_ wizard- > callbacks . open ( wizard_args ) ) ) {
ast_log ( LOG_WARNING , " Wizard '%s' failed to open mapping for object type '%s' with data: %s \n " ,
name, object_type - > name , S_OR ( data , " " ) ) ;
wizard_type_ name, object_type - > name , S_OR ( wizard_args , " " ) ) ;
AST_VECTOR_RW_UNLOCK ( & object_type - > wizards ) ;
ast_module_unref ( wizard- > callbacks . module ) ;
ast_module_unref ( internal_ wizard- > callbacks . module ) ;
return AST_SORCERY_APPLY_FAIL ;
}
object_wizard - > wizard = ao2_bump ( wizard ) ;
object_wizard - > caching = caching ;
object_wizard - > wizard = ao2_bump ( internal_wizard ) ;
object_wizard - > caching = ! ! ( flags & AST_SORCERY_WIZARD_APPLY_CACHING ) ;
object_wizard - > read_only = ! ! ( flags & AST_SORCERY_WIZARD_APPLY_READONLY ) ;
if ( wizard_args ) {
strcpy ( object_wizard - > wizard_args , wizard_args ) ; /* Safe */
}
if ( position = = AST_SORCERY_WIZARD_POSITION_LAST ) {
position = AST_VECTOR_SIZE ( & object_type - > wizards ) ;
@ -895,17 +944,36 @@ enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping(struct ast_sor
}
NOTIFY_INSTANCE_OBSERVERS ( sorcery - > observers , wizard_mapped ,
sorcery - > module_name , sorcery , type , & wizard - > callbacks , data , object_wizard - > data ) ;
sorcery - > module_name , sorcery , object_type_name , & internal_wizard - > callbacks , wizard_args ,
object_wizard - > data ) ;
if ( wizard ) {
* wizard = & internal_wizard - > callbacks ;
}
if ( wizard_data ) {
* wizard_data = object_wizard - > data ;
}
return AST_SORCERY_APPLY_SUCCESS ;
}
/*! \brief Internal function which creates an object type and inserts a wizard mapping */
enum ast_sorcery_apply_result __ast_sorcery_insert_wizard_mapping ( struct ast_sorcery * sorcery ,
const char * object_type_name , const char * module , const char * wizard_type_name ,
const char * wizard_args , unsigned int caching , int position )
{
return __ast_sorcery_object_type_insert_wizard ( sorcery , object_type_name , module , wizard_type_name ,
wizard_args , caching ? AST_SORCERY_WIZARD_APPLY_CACHING : AST_SORCERY_WIZARD_APPLY_NONE ,
position , NULL , NULL ) ;
}
/*! \brief Internal function which creates an object type and adds a wizard mapping */
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 )
const char * object_type_name , const char * module , const char * wizard_type_name ,
const char * wizard_args , unsigned int caching )
{
return __ast_sorcery_insert_wizard_mapping ( sorcery , type , module , name , data ,
caching , AST_SORCERY_WIZARD_POSITION_LAST ) ;
return __ast_sorcery_insert_wizard_mapping ( sorcery , object_type_name, module , wizard_type_name ,
wizard_args, caching, AST_SORCERY_WIZARD_POSITION_LAST ) ;
}
enum ast_sorcery_apply_result __ast_sorcery_apply_config ( struct ast_sorcery * sorcery , const char * name , const char * module )
@ -1904,7 +1972,7 @@ struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *s
/*! \brief Internal function which returns if the wizard has created the object */
static int sorcery_wizard_create ( const struct ast_sorcery_object_wizard * object_wizard , const struct sorcery_details * details )
{
if ( ! object_wizard - > wizard - > callbacks . create ) {
if ( ! object_wizard - > wizard - > callbacks . create | | object_wizard - > read_only ) {
ast_debug ( 5 , " Sorcery wizard '%s' does not support creation \n " , object_wizard - > wizard - > callbacks . name ) ;
return 0 ;
}
@ -2015,7 +2083,7 @@ static int sorcery_observers_notify_update(void *data)
/*! \brief Internal function which returns if a wizard has updated the object */
static int sorcery_wizard_update ( const struct ast_sorcery_object_wizard * object_wizard , const struct sorcery_details * details )
{
if ( ! object_wizard - > wizard - > callbacks . update ) {
if ( ! object_wizard - > wizard - > callbacks . update | | object_wizard - > read_only ) {
ast_debug ( 5 , " Sorcery wizard '%s' does not support updating \n " , object_wizard - > wizard - > callbacks . name ) ;
return 0 ;
}
@ -2103,7 +2171,7 @@ static int sorcery_observers_notify_delete(void *data)
/*! \brief Internal function which returns if a wizard has deleted the object */
static int sorcery_wizard_delete ( const struct ast_sorcery_object_wizard * object_wizard , const struct sorcery_details * details )
{
if ( ! object_wizard - > wizard - > callbacks . delete ) {
if ( ! object_wizard - > wizard - > callbacks . delete | | object_wizard - > read_only ) {
ast_debug ( 5 , " Sorcery wizard '%s' does not support deletion \n " , object_wizard - > wizard - > callbacks . name ) ;
return 0 ;
}