fixes astobj2 unlinking of multiple objects when OBJ_MULTIPLE was disabled
authorDavid Vossel <dvossel@digium.com>
Fri, 5 Feb 2010 21:21:05 +0000 (21:21 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 5 Feb 2010 21:21:05 +0000 (21:21 +0000)
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: https://origsvn.digium.com/svn/asterisk/trunk@245147 65c4cc65-6c06-0410-ace0-fbb531ad65f3

include/asterisk/astobj2.h
main/astobj2.c

index 689b639..1727978 100644 (file)
@@ -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,
index cbd4511..c119a28 100644 (file)
@@ -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);