aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2010-02-05 21:21:05 +0000
committerdvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b>2010-02-05 21:21:05 +0000
commit637d35675d2723214401655618dd07d74cd6128a (patch)
treef1274a1025eae458209e8780b51833be32a0a5e2
parentfbf9fd7f6e38c2bb5e77afd5de5569a2f33cce9f (diff)
fixes astobj2 unlinking of multiple objects when OBJ_MULTIPLE was disabled
When OBJ_MULTIPLE was off but OBJ_UNLINK was on, all the items in a bucket were being unlinked instead of just the first match. This fixes that. Review: https://reviewboard.asterisk.org/r/490/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@245147 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--include/asterisk/astobj2.h3
-rw-r--r--main/astobj2.c21
2 files changed, 15 insertions, 9 deletions
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 689b639b5..17279787c 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -666,7 +666,8 @@ enum search_flags {
* its refcount.
*/
OBJ_NODATA = (1 << 1),
- /*! Don't stop at the first match in ao2_callback().
+ /*! Don't stop at the first match in ao2_callback() unless the result of
+ * of the callback function == (CMP_STOP | CMP_MATCH).
*/
OBJ_MULTIPLE = (1 << 2),
/*! obj is an object of the same type as the one being searched for,
diff --git a/main/astobj2.c b/main/astobj2.c
index cbd4511f8..c119a28f8 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -593,8 +593,6 @@ static int cb_true_data(void *user_data, void *arg, void *data, int flags)
return CMP_MATCH;
}
-#define USE_CONTAINER(x) (((x) & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE)
-
/*!
* Browse the container using different stategies accoding the flags.
* \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
@@ -617,7 +615,12 @@ static void *internal_ao2_callback(struct ao2_container *c,
if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
return NULL;
- if (USE_CONTAINER(flags)) {
+ /*
+ * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
+ * turned off. This if statement checks for the special condition
+ * where multiple items may need to be returned.
+ */
+ if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
/* we need to return an ao2_iterator with the results,
* as there could be more than one. the iterator will
* hold the only reference to a container that has all the
@@ -707,10 +710,10 @@ static void *internal_ao2_callback(struct ao2_container *c,
}
}
- /* if we are in OBJ_MULTIPLE mode, link the object into the
- * container that will hold the results
+ /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off,
+ * link the object into the container that will hold the results.
*/
- if (ret && USE_CONTAINER(flags)) {
+ if (ret && (multi_container != NULL)) {
__ao2_link(multi_container, ret);
ret = NULL;
}
@@ -733,7 +736,7 @@ static void *internal_ao2_callback(struct ao2_container *c,
ast_free(cur); /* free the link record */
}
- if ((match & CMP_STOP) || USE_CONTAINER(flags)) {
+ if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
/* We found our only (or last) match, so force an exit from
the outside loop. */
i = last;
@@ -753,7 +756,9 @@ static void *internal_ao2_callback(struct ao2_container *c,
}
}
ao2_unlock(c);
- if (USE_CONTAINER(flags)) {
+
+ /* if multi_container was created, we are returning multiple objects */
+ if (multi_container != NULL) {
*multi_iterator = ao2_iterator_init(multi_container,
AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
ao2_ref(multi_container, -1);