diff options
Diffstat (limited to 'main/sorcery.c')
-rw-r--r-- | main/sorcery.c | 136 |
1 files changed, 120 insertions, 16 deletions
diff --git a/main/sorcery.c b/main/sorcery.c index 99e4c5586..cf4cd0213 100644 --- a/main/sorcery.c +++ b/main/sorcery.c @@ -58,6 +58,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") /*! \brief Thread pool for observers */ static struct ast_threadpool *threadpool; +/*! \brief Structure for internal sorcery object information */ +struct ast_sorcery_object { + /*! \brief Unique identifier of this object */ + char id[AST_UUID_STR_LEN]; + + /*! \brief Type of object */ + char type[MAX_OBJECT_TYPE]; + + /*! \brief Optional object destructor */ + ao2_destructor_fn destructor; + + /*! \brief Extended object fields */ + struct ast_variable *extended; +}; + /*! \brief Structure for registered object type */ struct ast_sorcery_object_type { /*! \brief Unique name of the object type */ @@ -525,6 +540,24 @@ int __ast_sorcery_apply_default(struct ast_sorcery *sorcery, const char *type, c return sorcery_apply_wizard_mapping(sorcery, type, module, name, data, 0); } +static int sorcery_extended_config_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + return ast_sorcery_object_set_extended(obj, var->name, var->value); +} + +static int sorcery_extended_fields_handler(const void *obj, struct ast_variable **fields) +{ + const struct ast_sorcery_object_details *details = obj; + + if (details->object->extended) { + *fields = ast_variables_dup(details->object->extended); + } else { + *fields = NULL; + } + + return 0; +} + int ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, aco_type_item_alloc alloc, sorcery_transform_handler transform, sorcery_apply_handler apply) { RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup); @@ -547,6 +580,10 @@ int ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, a return -1; } + if (ast_sorcery_object_fields_register(sorcery, type, "^@", sorcery_extended_config_handler, sorcery_extended_fields_handler)) { + return -1; + } + return 0; } @@ -784,7 +821,7 @@ void ast_sorcery_ref(struct ast_sorcery *sorcery) struct ast_variable *ast_sorcery_objectset_create(const struct ast_sorcery *sorcery, const void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); struct ao2_iterator i; struct ast_sorcery_object_field *object_field; struct ast_variable *fields = NULL; @@ -816,7 +853,7 @@ struct ast_variable *ast_sorcery_objectset_create(const struct ast_sorcery *sorc continue; } - if (!res) { + if (!res && tmp) { tmp->next = fields; fields = tmp; } @@ -836,7 +873,7 @@ struct ast_variable *ast_sorcery_objectset_create(const struct ast_sorcery *sorc struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sorcery, const void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); struct ao2_iterator i; struct ast_sorcery_object_field *object_field; struct ast_json *json = ast_json_object_create(); @@ -898,7 +935,7 @@ struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sor int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, struct ast_variable *objectset) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); RAII_VAR(struct ast_variable *, transformed, NULL, ast_variables_destroy); struct ast_variable *field; int res = 0; @@ -914,7 +951,7 @@ int ast_sorcery_objectset_apply(const struct ast_sorcery *sorcery, void *object, } for (; field; field = field->next) { - if ((res = aco_process_var(&object_type->type, details->id, field, object))) { + if ((res = aco_process_var(&object_type->type, details->object->id, field, object))) { break; } } @@ -977,6 +1014,32 @@ int ast_sorcery_changeset_create(const struct ast_variable *original, const stru return res; } +static void sorcery_object_destructor(void *object) +{ + struct ast_sorcery_object_details *details = object; + + if (details->object->destructor) { + details->object->destructor(object); + } + + ast_variables_destroy(details->object->extended); +} + +void *ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor) +{ + void *object = ao2_alloc_options(size + sizeof(struct ast_sorcery_object), sorcery_object_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK); + struct ast_sorcery_object_details *details = object; + + if (!object) { + return NULL; + } + + details->object = object + size; + details->object->destructor = destructor; + + return object; +} + void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, const char *id) { RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup); @@ -988,12 +1051,12 @@ void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, con } if (ast_strlen_zero(id)) { - ast_uuid_generate_str(details->id, sizeof(details->id)); + ast_uuid_generate_str(details->object->id, sizeof(details->object->id)); } else { - ast_copy_string(details->id, id, sizeof(details->id)); + ast_copy_string(details->object->id, id, sizeof(details->object->id)); } - ast_copy_string(details->type, type, sizeof(details->type)); + ast_copy_string(details->object->type, type, sizeof(details->object->type)); if (aco_set_defaults(&object_type->type, id, details)) { ao2_ref(details, -1); @@ -1006,8 +1069,8 @@ void *ast_sorcery_alloc(const struct ast_sorcery *sorcery, const char *type, con void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); - struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->type, details->id); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); + struct ast_sorcery_object_details *copy = ast_sorcery_alloc(sorcery, details->object->type, details->object->id); RAII_VAR(struct ast_variable *, objectset, NULL, ast_variables_destroy); int res = 0; @@ -1120,7 +1183,6 @@ void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const ch unsigned int cached = 0; if (!object_type) { - ast_log(LOG_NOTICE, "Can't find object type '%s'\n", type); return NULL; } @@ -1222,7 +1284,7 @@ static int sorcery_observers_notify_create(void *data) int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup); struct sorcery_details sdetails = { .sorcery = sorcery, @@ -1281,7 +1343,7 @@ static int sorcery_wizard_update(void *obj, void *arg, int flags) int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup); struct sorcery_details sdetails = { .sorcery = sorcery, @@ -1340,7 +1402,7 @@ static int sorcery_wizard_delete(void *obj, void *arg, int flags) int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object) { const struct ast_sorcery_object_details *details = object; - RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->type, OBJ_KEY), ao2_cleanup); + RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, details->object->type, OBJ_KEY), ao2_cleanup); RAII_VAR(struct ast_sorcery_object_wizard *, object_wizard, NULL, ao2_cleanup); struct sorcery_details sdetails = { .sorcery = sorcery, @@ -1371,13 +1433,55 @@ void ast_sorcery_unref(struct ast_sorcery *sorcery) const char *ast_sorcery_object_get_id(const void *object) { const struct ast_sorcery_object_details *details = object; - return details->id; + return details->object->id; } const char *ast_sorcery_object_get_type(const void *object) { const struct ast_sorcery_object_details *details = object; - return details->type; + return details->object->type; +} + +const char *ast_sorcery_object_get_extended(const void *object, const char *name) +{ + const struct ast_sorcery_object_details *details = object; + struct ast_variable *field; + + for (field = details->object->extended; field; field = field->next) { + if (!strcmp(field->name + 1, name)) { + return field->value; + } + } + + return NULL; +} + +int ast_sorcery_object_set_extended(const void *object, const char *name, const char *value) +{ + RAII_VAR(struct ast_variable *, field, NULL, ast_variables_destroy); + struct ast_variable *extended = ast_variable_new(name, value, ""), *previous = NULL; + const struct ast_sorcery_object_details *details = object; + + if (!extended) { + return -1; + } + + for (field = details->object->extended; field; previous = field, field = field->next) { + if (!strcmp(field->name, name)) { + if (previous) { + previous->next = field->next; + } else { + details->object->extended = field->next; + } + field->next = NULL; + break; + } + } + + extended->next = details->object->extended; + details->object->extended = extended; + + return 0; } int ast_sorcery_observer_add(const struct ast_sorcery *sorcery, const char *type, const struct ast_sorcery_observer *callbacks) |