summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorJoshua Colp <jcolp@digium.com>2013-02-10 14:58:37 +0000
committerJoshua Colp <jcolp@digium.com>2013-02-10 14:58:37 +0000
commit27882b859976103e4e039b0107c0290604b17380 (patch)
tree287554cf4890bc30e0ddf9adfe8611a01ebc3878 /main
parent0e442112ada90d53cf8991b63bd3970cfaa7cc7a (diff)
Add additional functionality to the Sorcery API.
This commit adds native implementation support for copying and diffing objects, as well as the ability to load or reload on a per-object type level. Review: https://reviewboard.asterisk.org/r/2320/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@381134 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/sorcery.c99
1 files changed, 88 insertions, 11 deletions
diff --git a/main/sorcery.c b/main/sorcery.c
index bed4d8533..f9ff6d563 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -63,6 +63,12 @@ struct ast_sorcery_object_type {
/*! \brief Optional object set apply callback */
sorcery_apply_handler apply;
+ /*! \brief Optional object copy callback */
+ sorcery_copy_handler copy;
+
+ /*! \brief Optional object diff callback */
+ sorcery_diff_handler diff;
+
/*! \brief Wizard instances */
struct ao2_container *wizards;
@@ -299,7 +305,7 @@ struct ast_sorcery *ast_sorcery_open(void)
return NULL;
}
- if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
+ if (!(sorcery->types = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, TYPE_BUCKETS, sorcery_type_hash, sorcery_type_cmp))) {
ao2_ref(sorcery, -1);
sorcery = NULL;
}
@@ -467,7 +473,7 @@ int ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, a
{
RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
- if (!object_type) {
+ if (!object_type || object_type->type.item_alloc) {
return -1;
}
@@ -487,6 +493,28 @@ int ast_sorcery_object_register(struct ast_sorcery *sorcery, const char *type, a
return 0;
}
+void ast_sorcery_object_set_copy_handler(struct ast_sorcery *sorcery, const char *type, sorcery_copy_handler copy)
+{
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+
+ if (!object_type) {
+ return;
+ }
+
+ object_type->copy = copy;
+}
+
+void ast_sorcery_object_set_diff_handler(struct ast_sorcery *sorcery, const char *type, sorcery_diff_handler diff)
+{
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+
+ if (!object_type) {
+ return;
+ }
+
+ object_type->diff = diff;
+}
+
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, unsigned int flags, size_t argc, ...)
{
@@ -573,6 +601,21 @@ void ast_sorcery_load(const struct ast_sorcery *sorcery)
ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
}
+void ast_sorcery_load_object(const struct ast_sorcery *sorcery, const char *type)
+{
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+ struct sorcery_load_details details = {
+ .sorcery = sorcery,
+ .reload = 0,
+ };
+
+ if (!object_type) {
+ return;
+ }
+
+ sorcery_object_load(object_type, &details, 0);
+}
+
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
{
struct sorcery_load_details details = {
@@ -583,6 +626,21 @@ void ast_sorcery_reload(const struct ast_sorcery *sorcery)
ao2_callback(sorcery->types, OBJ_NODATA, sorcery_object_load, &details);
}
+void ast_sorcery_reload_object(const struct ast_sorcery *sorcery, const char *type)
+{
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+ struct sorcery_load_details details = {
+ .sorcery = sorcery,
+ .reload = 1,
+ };
+
+ if (!object_type) {
+ return;
+ }
+
+ sorcery_object_load(object_type, &details, 0);
+}
+
void ast_sorcery_ref(struct ast_sorcery *sorcery)
{
ao2_ref(sorcery, +1);
@@ -753,14 +811,25 @@ 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_variable *, objectset, NULL, ast_variables_destroy);
+ int res = 0;
- if (!copy ||
- !(objectset = ast_sorcery_objectset_create(sorcery, object)) ||
- ast_sorcery_objectset_apply(sorcery, copy, objectset)) {
- ao2_cleanup(copy);
+ if (!copy) {
return NULL;
+ } else if (object_type->copy) {
+ res = object_type->copy(object, copy);
+ } else if ((objectset = ast_sorcery_objectset_create(sorcery, object))) {
+ res = ast_sorcery_objectset_apply(sorcery, copy, objectset);
+ } else {
+ /* No native copy available and could not create an objectset, this copy has failed */
+ res = -1;
+ }
+
+ if (res) {
+ ao2_cleanup(copy);
+ copy = NULL;
}
return copy;
@@ -768,8 +837,7 @@ void *ast_sorcery_copy(const struct ast_sorcery *sorcery, const void *object)
int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, const void *modified, struct ast_variable **changes)
{
- RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
- RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, ast_sorcery_object_get_type(original), OBJ_KEY), ao2_cleanup);
*changes = NULL;
@@ -777,10 +845,19 @@ int ast_sorcery_diff(const struct ast_sorcery *sorcery, const void *original, co
return -1;
}
- objectset1 = ast_sorcery_objectset_create(sorcery, original);
- objectset2 = ast_sorcery_objectset_create(sorcery, modified);
+ if (original == modified) {
+ return 0;
+ } else if (!object_type->diff) {
+ RAII_VAR(struct ast_variable *, objectset1, NULL, ast_variables_destroy);
+ RAII_VAR(struct ast_variable *, objectset2, NULL, ast_variables_destroy);
- return ast_sorcery_changeset_create(objectset1, objectset2, changes);
+ objectset1 = ast_sorcery_objectset_create(sorcery, original);
+ objectset2 = ast_sorcery_objectset_create(sorcery, modified);
+
+ return ast_sorcery_changeset_create(objectset1, objectset2, changes);
+ } else {
+ return object_type->diff(original, modified, changes);
+ }
}
/*! \brief Internal function used to create an object in caching wizards */