summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Joseph <george.joseph@fairview5.com>2016-02-25 14:13:19 -0700
committerGeorge Joseph <george.joseph@fairview5.com>2016-02-29 11:31:18 -0600
commit48d713a83232fc51fc95d2e50a72c67980e63354 (patch)
tree8259a8eacd03391867d8a152b40d6a844b6ee54f
parentd35c494df1bfc1cc44d7483d9750f31d0184d020 (diff)
sorcery: Refactor create, update and delete to better deal with caches
The ast_sorcery_create, update and delete function have been refactored to better deal with caches and errors. The action is now called on all non-caching wizards first. If ANY succeed, the action is called on all caching wizards and the observers are notified. This way we don't put something in the cache (or update or delete) before knowing the action was performed in at least 1 backend and we only call the observers once even if there were multiple writable backends. ast_sorcery_create was never adding to caches in the first place which was preventing contacts from getting added to a memory_cache when they were created. In turn this was causing memory_cache to emit errors if the contact was deleted before being retrieved (which would have populated the cache). ASTERISK-25811 #close Reported-by: Ross Beer Change-Id: Id5596ce691685a79886e57b0865888458d6e7b46
-rw-r--r--main/sorcery.c99
1 files changed, 76 insertions, 23 deletions
diff --git a/main/sorcery.c b/main/sorcery.c
index 774d001a6..3a29cfa58 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -1953,7 +1953,12 @@ static int sorcery_wizard_create(void *obj, void *arg, int flags)
ast_debug(5, "Sorcery wizard '%s' does not support creation\n", object_wizard->wizard->callbacks.name);
return 0;
}
- return (!object_wizard->caching && !object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) ? CMP_MATCH | CMP_STOP : 0;
+
+ if (object_wizard->wizard->callbacks.create(details->sorcery, object_wizard->data, details->obj)) {
+ return 0;
+ }
+
+ return CMP_MATCH;
}
/*! \brief Internal callback function which notifies an individual observer that an object has been created */
@@ -1998,17 +2003,31 @@ int ast_sorcery_create(const struct ast_sorcery *sorcery, void *object)
AST_VECTOR_RW_RDLOCK(&object_type->wizards);
for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
- if (sorcery_wizard_create(found_wizard, &sdetails, 0) == (CMP_MATCH | CMP_STOP)) {
+ if (!found_wizard->caching && sorcery_wizard_create(found_wizard, &sdetails, 0) == CMP_MATCH) {
object_wizard = found_wizard;
- if(ao2_container_count(object_type->observers)) {
- struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
+ }
+ }
- if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create, invocation)) {
- ao2_cleanup(invocation);
- }
+ if (object_wizard) {
+ for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
+ found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
+ if (found_wizard->caching) {
+ sorcery_wizard_create(found_wizard, &sdetails, 0);
+ }
+ }
+
+ if (ao2_container_count(object_type->observers)) {
+ struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(
+ object_type, object);
+
+ if (invocation
+ && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_create,
+ invocation)) {
+ ao2_cleanup(invocation);
}
}
}
+
AST_VECTOR_RW_UNLOCK(&object_type->wizards);
return object_wizard ? 0 : -1;
@@ -2048,8 +2067,11 @@ static int sorcery_wizard_update(void *obj, void *arg, int flags)
return 0;
}
- return (!object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj) &&
- !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
+ if (object_wizard->wizard->callbacks.update(details->sorcery, object_wizard->data, details->obj)) {
+ return 0;
+ }
+
+ return CMP_MATCH;
}
int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
@@ -2071,17 +2093,31 @@ int ast_sorcery_update(const struct ast_sorcery *sorcery, void *object)
AST_VECTOR_RW_RDLOCK(&object_type->wizards);
for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
- if (sorcery_wizard_update(found_wizard, &sdetails, 0) == (CMP_MATCH | CMP_STOP)) {
+ if (!found_wizard->caching && sorcery_wizard_update(found_wizard, &sdetails, 0) == CMP_MATCH) {
object_wizard = found_wizard;
- if (ao2_container_count(object_type->observers)) {
- struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
+ }
+ }
- if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update, invocation)) {
- ao2_cleanup(invocation);
- }
+ if (object_wizard) {
+ for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
+ found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
+ if (found_wizard->caching) {
+ sorcery_wizard_update(found_wizard, &sdetails, 0);
+ }
+ }
+
+ if (ao2_container_count(object_type->observers)) {
+ struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(
+ object_type, object);
+
+ if (invocation
+ && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_update,
+ invocation)) {
+ ao2_cleanup(invocation);
}
}
}
+
AST_VECTOR_RW_UNLOCK(&object_type->wizards);
return object_wizard ? 0 : -1;
@@ -2121,8 +2157,11 @@ static int sorcery_wizard_delete(void *obj, void *arg, int flags)
return 0;
}
- return (!object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj) &&
- !object_wizard->caching) ? CMP_MATCH | CMP_STOP : 0;
+ if (object_wizard->wizard->callbacks.delete(details->sorcery, object_wizard->data, details->obj)) {
+ return 0;
+ }
+
+ return CMP_MATCH;
}
int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
@@ -2144,17 +2183,31 @@ int ast_sorcery_delete(const struct ast_sorcery *sorcery, void *object)
AST_VECTOR_RW_RDLOCK(&object_type->wizards);
for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
- if (sorcery_wizard_delete(found_wizard, &sdetails, 0) == (CMP_MATCH | CMP_STOP)) {
+ if (!found_wizard->caching && sorcery_wizard_delete(found_wizard, &sdetails, 0) == CMP_MATCH) {
object_wizard = found_wizard;
- if (ao2_container_count(object_type->observers)) {
- struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(object_type, object);
+ }
+ }
- if (invocation && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete, invocation)) {
- ao2_cleanup(invocation);
- }
+ if (object_wizard) {
+ for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
+ found_wizard = AST_VECTOR_GET(&object_type->wizards, i);
+ if (found_wizard->caching) {
+ sorcery_wizard_delete(found_wizard, &sdetails, 0);
+ }
+ }
+
+ if (ao2_container_count(object_type->observers)) {
+ struct sorcery_observer_invocation *invocation = sorcery_observer_invocation_alloc(
+ object_type, object);
+
+ if (invocation
+ && ast_taskprocessor_push(object_type->serializer, sorcery_observers_notify_delete,
+ invocation)) {
+ ao2_cleanup(invocation);
}
}
}
+
AST_VECTOR_RW_UNLOCK(&object_type->wizards);
return object_wizard ? 0 : -1;