[svn-commits] kpfleming: trunk r225244 - in /trunk: apps/ funcs/ include/asterisk/ main/ re...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Oct 21 16:08:51 CDT 2009


Author: kpfleming
Date: Wed Oct 21 16:08:47 2009
New Revision: 225244

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=225244
Log:
Finish implementaton of astobj2 OBJ_MULTIPLE, and convert ast_channel_iterator to use it.

This patch finishes the implementation of OBJ_MULTIPLE in astobj2 (the
case where multiple results need to be returned; OBJ_NODATA mode
already was supported). In addition, it converts ast_channel_iterators
(only the targeted versions, not the ones that iterate over all
channels) to use this method.

During this work, I removed the 'ao2_flags' arguments to the
ast_channel_iterator constructor functions; there were no uses of that
argument yet, there is only one possible flag to pass, and it made the
iterators less 'opaque'. If at some point in the future someone really
needs an ast_channel_iterator that does not lock the container, we can
provide constructor(s) for that purpose.

Review: https://reviewboard.asterisk.org/r/379/


Modified:
    trunk/apps/app_chanspy.c
    trunk/apps/app_directed_pickup.c
    trunk/apps/app_softhangup.c
    trunk/funcs/func_channel.c
    trunk/include/asterisk/astobj2.h
    trunk/include/asterisk/channel.h
    trunk/include/asterisk/lock.h
    trunk/main/astobj2.c
    trunk/main/channel.c
    trunk/main/cli.c
    trunk/main/manager.c
    trunk/res/snmp/agent.c

Modified: trunk/apps/app_chanspy.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_chanspy.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/apps/app_chanspy.c (original)
+++ trunk/apps/app_chanspy.c Wed Oct 21 16:08:47 2009
@@ -786,11 +786,11 @@
 
 		/* Set up the iterator we'll be using during this call */
 		if (!ast_strlen_zero(spec)) {
-			iter = ast_channel_iterator_by_name_new(0, spec, strlen(spec));
+			iter = ast_channel_iterator_by_name_new(spec, strlen(spec));
 		} else if (!ast_strlen_zero(exten)) {
-			iter = ast_channel_iterator_by_exten_new(0, exten, context);
+			iter = ast_channel_iterator_by_exten_new(exten, context);
 		} else {
-			iter = ast_channel_iterator_all_new(0);
+			iter = ast_channel_iterator_all_new();
 		}
 
 		if (!iter) {

Modified: trunk/apps/app_directed_pickup.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_directed_pickup.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/apps/app_directed_pickup.c (original)
+++ trunk/apps/app_directed_pickup.c Wed Oct 21 16:08:47 2009
@@ -210,7 +210,7 @@
 	struct ast_channel_iterator *iter;
 	int res = -1;
 
-	if (!(iter = ast_channel_iterator_by_exten_new(0, exten, context))) {
+	if (!(iter = ast_channel_iterator_by_exten_new(exten, context))) {
 		return -1;
 	}
 
@@ -222,6 +222,8 @@
 		ast_channel_unlock(target);
 		target = ast_channel_unref(target);
 	}
+
+	ast_channel_iterator_destroy(iter);
 
 	if (target) {
 		res = pickup_do(chan, target);

Modified: trunk/apps/app_softhangup.c
URL: http://svnview.digium.com/svn/asterisk/trunk/apps/app_softhangup.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/apps/app_softhangup.c (original)
+++ trunk/apps/app_softhangup.c Wed Oct 21 16:08:47 2009
@@ -94,7 +94,7 @@
 		ast_app_parse_options(app_opts, &flags, opts, args.options);
 	lenmatch = strlen(args.channel);
 
-	if (!(iter = ast_channel_iterator_by_name_new(0, args.channel, lenmatch))) {
+	if (!(iter = ast_channel_iterator_by_name_new(args.channel, lenmatch))) {
 		return -1;
 	}
 

Modified: trunk/funcs/func_channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/funcs/func_channel.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/funcs/func_channel.c (original)
+++ trunk/funcs/func_channel.c Wed Oct 21 16:08:47 2009
@@ -465,7 +465,7 @@
 		}
 	}
 
-	if (!(iter = ast_channel_iterator_all_new(0))) {
+	if (!(iter = ast_channel_iterator_all_new())) {
 		if (!ast_strlen_zero(data)) {
 			regfree(&re);
 		}

Modified: trunk/include/asterisk/astobj2.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/astobj2.h?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/include/asterisk/astobj2.h (original)
+++ trunk/include/asterisk/astobj2.h Wed Oct 21 16:08:47 2009
@@ -18,6 +18,7 @@
 #define _ASTERISK_ASTOBJ2_H
 
 #include "asterisk/compat.h"
+#include "asterisk/linkedlists.h"
 
 /*! \file
  * \ref AstObj2
@@ -547,7 +548,7 @@
     can be:
 	OBJ_UNLINK - to remove the object, once found, from the container.
 	OBJ_NODATA - don't return the object if found (no ref count change)
-	OBJ_MULTIPLE - don't stop at first match (not fully implemented)
+	OBJ_MULTIPLE - don't stop at first match
 	OBJ_POINTER	- if set, 'arg' is an object pointer, and a hashtable
                   search will be done. If not, a traversal is done.
 
@@ -559,7 +560,7 @@
       - flags can be
 	     OBJ_UNLINK   - to remove the object, once found, from the container.
 	     OBJ_NODATA   - don't return the object if found (no ref count change)
-	     OBJ_MULTIPLE - don't stop at first match (not fully implemented)
+	     OBJ_MULTIPLE - don't stop at first match
 	     OBJ_POINTER  - if set, 'arg' is an object pointer, and a hashtable
                         search will be done. If not, a traversal is done through
                         all the hashtable 'buckets'..
@@ -658,22 +659,21 @@
  */
 enum search_flags {
 	/*! Unlink the object for which the callback function
-	 *  returned CMP_MATCH . This is the only way to extract
-	 *  objects from a container. */
+	 *  returned CMP_MATCH.
+	 */
 	OBJ_UNLINK	 = (1 << 0),
 	/*! On match, don't return the object hence do not increase
-	 *  its refcount. */
+	 *  its refcount.
+	 */
 	OBJ_NODATA	 = (1 << 1),
-	/*! Don't stop at the first match in ao2_callback()
-	 *  \note This is not fully implemented.   Using OBJ_MULTIME with OBJ_NODATA
-	 *  is perfectly fine.  The part that is not implemented is the case where
-	 *  multiple objects should be returned by ao2_callback().
+	/*! Don't stop at the first match in ao2_callback().
 	 */
 	OBJ_MULTIPLE = (1 << 2),
 	/*! obj is an object of the same type as the one being searched for,
 	 *  so use the object's hash function for optimized searching.
 	 *  The search function is unaffected (i.e. use the one passed as
-	 *  argument, or match_by_addr if none specified). */
+	 *  argument, or match_by_addr if none specified).
+	 */
 	OBJ_POINTER	 = (1 << 3),
 	/*! 
 	 * \brief Continue if a match is not found in the hashed out bucket
@@ -816,12 +816,6 @@
 void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *file, int line, const char *funcname);
 void *__ao2_unlink(struct ao2_container *c, void *obj);
 
-
-/*! \brief Used as return value if the flag OBJ_MULTIPLE is set */
-struct ao2_list {
-	struct ao2_list *next;
-	void *obj;	/* pointer to the user portion of the object */
-};
 
 /*@} */
 
@@ -847,21 +841,22 @@
     should immediately stop, or both (via bitwise ORing), if you find a
     match and want to end the traversal, and 0 if the object is not a match,
     but the traversal should continue. This is the function that is applied
-    to each object traversed. It's arguments are:
+    to each object traversed. Its arguments are:
         (void *obj, void *arg, int flags), where:
           obj is an object
           arg is the same as arg passed into ao2_callback
           flags is the same as flags passed into ao2_callback (flags are
            also used by ao2_callback).
  * \param arg passed to the callback.
- * \return 	A pointer to the object found/marked,
- * 		a pointer to a list of objects matching comparison function,
- * 		NULL if not found.
+ * \return when OBJ_MULTIPLE is not included in the flags parameter,
+ *         the return value will be either the object found or NULL if no
+ *         no matching object was found. if OBJ_MULTIPLE is included,
+ *         the return value will be a pointer to an ao2_iterator object,
+ *         which must be destroyed with ao2_iterator_destroy() when the
+ *         caller no longer needs it.
  *
  * If the function returns any objects, their refcount is incremented,
  * and the caller is in charge of decrementing them once done.
- * Also, in case of multiple values returned, the list used
- * to store the objects must be freed by the caller.
  *
  * Typically, ao2_callback() is used for two purposes:
  * - to perform some action (including removal from the container) on one
@@ -881,9 +876,7 @@
  * we can say this looking at flags value.
  * If p points to an object we will search for the object pointed
  * by this value, otherwise we serch for a key value.
- * If the key is not uniq we only find the first matching valued.
- * If we use the OBJ_MARK flags, we mark all the objects matching
- * the condition.
+ * If the key is not unique we only find the first matching valued.
  *
  * The use of flags argument is the follow:
  *
@@ -892,12 +885,8 @@
  *				Callbacks use OBJ_NODATA as a default
  *				functions such as find() do
  *	OBJ_MULTIPLE		return multiple matches
- *				Default for _find() is no.
- *				to a key (not yet supported)
+ *				Default is no.
  *	OBJ_POINTER 		the pointer is an object pointer
- *
- * In case we return a list, the callee must take care to destroy
- * that list when no longer used.
  *
  * \note When the returned object is no longer in use, ao2_ref() should
  * be used to free the additional reference possibly created by this function.
@@ -1078,6 +1067,15 @@
 	 * while retrieving the next object from it.
 	 */
 	AO2_ITERATOR_DONTLOCK = (1 << 0),
+	/*! Indicates that the iterator was dynamically allocated by
+	 * astobj2 API and should be freed by ao2_iterator_destroy().
+	 */
+	AO2_ITERATOR_MALLOCD = (1 << 1),
+	/*! Indicates that before the iterator returns an object from
+	 * the container being iterated, the object should be unlinked
+	 * from the container.
+	 */
+	AO2_ITERATOR_UNLINK = (1 << 2),
 };
 
 /*!

Modified: trunk/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Wed Oct 21 16:08:47 2009
@@ -2210,7 +2210,6 @@
 /*!
  * \brief Create a new channel iterator based on extension
  *
- * \arg ao2_flags astobj2 iterator flags
  * \arg exten The extension that channels must be in
  * \arg context The context that channels must be in (optional)
  *
@@ -2223,13 +2222,11 @@
  *
  * \since 1.6.3
  */
-struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten,
-	const char *context);
+struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context);
 
 /*!
  * \brief Create a new channel iterator based on name
  *
- * \arg ao2_flags astobj2 iterator flags
  * \arg name channel name or channel uniqueid to match
  * \arg name_len number of characters in the channel name to match on.  This
  *      would be used to match based on name prefix.  If matching on the full
@@ -2244,13 +2241,10 @@
  *
  * \since 1.6.3
  */
-struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name,
-	size_t name_len);
+struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name,	size_t name_len);
 
 /*!
  * \brief Create a new channel iterator
- *
- * \arg ao2_flags astobj2 iterator flags
  *
  * After creating an iterator using this function, the ast_channel_iterator_next()
  * function can be used to iterate through all channels that exist.
@@ -2260,7 +2254,7 @@
  *
  * \since 1.6.3
  */
-struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags);
+struct ast_channel_iterator *ast_channel_iterator_all_new(void);
 
 /*!
  * \brief Get the next channel for a channel iterator

Modified: trunk/include/asterisk/lock.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/lock.h?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/include/asterisk/lock.h (original)
+++ trunk/include/asterisk/lock.h Wed Oct 21 16:08:47 2009
@@ -60,7 +60,6 @@
 #endif
 
 #include "asterisk/logger.h"
-#include "asterisk/astobj2.h"
 
 /* internal macro to profile mutexes. Only computes the delay on
  * non-blocking calls.

Modified: trunk/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/astobj2.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/main/astobj2.c (original)
+++ trunk/main/astobj2.c Wed Oct 21 16:08:47 2009
@@ -292,7 +292,7 @@
 		 * first word of the user-data, which we make sure is always
 		 * allocated. */
 		memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
-		free(obj);
+		ast_free(obj);
 	}
 
 	return ret;
@@ -609,13 +609,27 @@
 	void *ret = NULL;
 	ao2_callback_fn *cb_default = NULL;
 	ao2_callback_data_fn *cb_withdata = NULL;
+	struct ao2_container *multi_container = NULL;
+	struct ao2_iterator *multi_iterator = NULL;
 
 	if (INTERNAL_OBJ(c) == NULL)	/* safety check on the argument */
 		return NULL;
 
 	if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
-		ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags);
-		return NULL;
+		/* 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
+		 * matching objects linked into it, so when the iterator
+		 * is destroyed, the container will be automatically
+		 * destroyed as well.
+		 */
+		if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) {
+			return NULL;
+		}
+		if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
+			ao2_ref(multi_container, -1);
+			return NULL;
+		}
 	}
 
 	/* override the match function if necessary */
@@ -627,7 +641,7 @@
 		}
 	} else {
 		/* We do this here to avoid the per object casting penalty (even though
-		   that is probably optimized away anyway. */
+		   that is probably optimized away anyway). */
 		if (type == WITH_DATA) {
 			cb_withdata = cb_fn;
 		} else {
@@ -678,49 +692,51 @@
 				i = last;
 				break;
 			}
+
 			/* we have a match (CMP_MATCH) here */
 			if (!(flags & OBJ_NODATA)) {	/* if must return the object, record the value */
 				/* it is important to handle this case before the unlink */
 				ret = EXTERNAL_OBJ(cur->astobj);
-				if (tag)
-					__ao2_ref_debug(ret, 1, tag, file, line, funcname);
-				else
-					__ao2_ref(ret, 1);
+				if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
+					if (tag)
+						__ao2_ref_debug(ret, 1, tag, file, line, funcname);
+					else
+						__ao2_ref(ret, 1);
+				}
 			}
 
+			/* if we are in OBJ_MULTIPLE mode, link the object into the
+			 * container that will hold the results
+			 */
+			if (ret && (multi_container != NULL)) {
+				__ao2_link(multi_container, ret);
+				ret = NULL;
+			}
+
 			if (flags & OBJ_UNLINK) {	/* must unlink */
-				struct bucket_list *x = cur;
-
 				/* we are going to modify the container, so update version */
 				ast_atomic_fetchadd_int(&c->version, 1);
 				AST_LIST_REMOVE_CURRENT(entry);
-				/* update number of elements and version */
+				/* update number of elements */
 				ast_atomic_fetchadd_int(&c->elements, -1);
-				if (tag)
-					__ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname);
-				else
-					__ao2_ref(EXTERNAL_OBJ(x->astobj), -1);
-				free(x);	/* free the link record */
+				if (!(flags & OBJ_NODATA)) {
+					if (tag)
+						__ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
+					else
+						__ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
+				}
+				ast_free(cur);	/* free the link record */
 			}
 
-			if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) {
+			if ((match & CMP_STOP) || (multi_container == NULL)) {
 				/* We found the only match we need */
 				i = last;	/* force exit from outer loop */
 				break;
 			}
-			if (!(flags & OBJ_NODATA)) {
-#if 0	/* XXX to be completed */
-				/*
-				 * This is the multiple-return case. We need to link
-				 * the object in a list. The refcount is already increased.
-				 */
-#endif
-			}
 		}
 		AST_LIST_TRAVERSE_SAFE_END;
 
 		if (ret) {
-			/* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */
 			break;
 		}
 
@@ -731,7 +747,14 @@
 		}
 	}
 	ao2_unlock(c);
-	return ret;
+	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);
+		return multi_iterator;
+	} else {
+		return ret;
+	}
 }
 
 void *__ao2_callback_debug(struct ao2_container *c,
@@ -796,7 +819,11 @@
 void ao2_iterator_destroy(struct ao2_iterator *i)
 {
 	ao2_ref(i->c, -1);
-	i->c = NULL;
+	if (i->flags & AO2_ITERATOR_MALLOCD) {
+		ast_free(i);
+	} else {
+		i->c = NULL;
+	}
 }
 
 /*
@@ -819,8 +846,8 @@
 	/* optimization. If the container is unchanged and
 	 * we have a pointer, try follow it
 	 */
-	if (a->c->version == a->c_version && (p = a->obj) ) {
-		if ( (p = AST_LIST_NEXT(p, entry)) )
+	if (a->c->version == a->c_version && (p = a->obj)) {
+		if ((p = AST_LIST_NEXT(p, entry)))
 			goto found;
 		/* nope, start from the next bucket */
 		a->bucket++;
@@ -846,12 +873,24 @@
 
 found:
 	if (p) {
-		a->version = p->version;
-		a->obj = p;
-		a->c_version = a->c->version;
 		ret = EXTERNAL_OBJ(p->astobj);
-		/* inc refcount of returned object */
-		*q = p;
+		if (a->flags & AO2_ITERATOR_UNLINK) {
+			/* we are going to modify the container, so update version */
+			ast_atomic_fetchadd_int(&a->c->version, 1);
+			AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
+			/* update number of elements */
+			ast_atomic_fetchadd_int(&a->c->elements, -1);
+			a->version = 0;
+			a->obj = NULL;
+			a->c_version = a->c->version;
+			ast_free(p);
+		} else {
+			a->version = p->version;
+			a->obj = p;
+			a->c_version = a->c->version;
+			/* inc refcount of returned object */
+			*q = p;
+		}
 	}
 
 	return ret;

Modified: trunk/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Wed Oct 21 16:08:47 2009
@@ -1234,137 +1234,83 @@
 }
 
 struct ast_channel_iterator {
-	struct ao2_iterator i;
-	const char *name;
-	size_t name_len;
-	const char *exten;
-	const char *context;
+	/* storage for non-dynamically allocated iterator */
+	struct ao2_iterator simple_iterator;
+	/* pointer to the actual iterator (simple_iterator or a dynamically
+	 * allocated iterator)
+	 */
+	struct ao2_iterator *active_iterator;
 };
 
 struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i)
 {
-	if (i->name) {
-		ast_free((void *) i->name);
-		i->name = NULL;
-	}
-
-	if (i->exten) {
-		ast_free((void *) i->exten);
-		i->exten = NULL;
-	}
-
-	if (i->context) {
-		ast_free((void *) i->context);
-		i->context = NULL;
-	}
-
+	ao2_iterator_destroy(i->active_iterator);
 	ast_free(i);
 
 	return NULL;
 }
 
-static struct ast_channel_iterator *ast_channel_iterator_new(int ao2_flags, const char *name,
-	size_t name_len, const char *exten, const char *context)
+static struct ast_channel_iterator *channel_iterator_search(const char *name,
+							    size_t name_len, const char *exten,
+							    const char *context)
 {
 	struct ast_channel_iterator *i;
+	struct ast_channel tmp_chan = {
+		.name = name,
+		/* This is sort of a hack.  Basically, we're using an arbitrary field
+		 * in ast_channel to pass the name_len for a prefix match.  If this
+		 * gets changed, then the compare callback must be changed, too. */
+		.rings = name_len,
+	};
 
 	if (!(i = ast_calloc(1, sizeof(*i)))) {
 		return NULL;
 	}
 
-	if (!ast_strlen_zero(exten) && !(i->exten = ast_strdup(exten))) {
-		goto return_error;
-	}
-
-	if (!ast_strlen_zero(context) && !(i->context = ast_strdup(context))) {
-		goto return_error;
-	}
-
-	if (!ast_strlen_zero(name) && !(i->name = ast_strdup(name))) {
-		goto return_error;
-	}
-
-	i->name_len = name_len;
-
-	i->i = ao2_iterator_init(channels, ao2_flags);
+	if (exten) {
+		ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten));
+	}
+
+	if (context) {
+		ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context));
+	}
+
+	if (!(i->active_iterator = ao2_find(channels, &tmp_chan,
+					    OBJ_MULTIPLE | ((!ast_strlen_zero(name) && (name_len == 0)) ? OBJ_POINTER : 0)))) {
+		    ast_free(i);
+		    return NULL;
+	}
 
 	return i;
-
-return_error:
-	if (i->exten) {
-		ast_free((void *) i->exten);
-		i->exten = NULL;
-	}
-
-	if (i->context) {
-		ast_free((void *) i->context);
-		i->context = NULL;
-	}
-
-	ast_free(i);
-
-	return NULL;
-}
-
-struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, const char *exten,
-	const char *context)
-{
-	return ast_channel_iterator_new(ao2_flags, NULL, 0, exten, context);
-}
-
-struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, const char *name,
-	size_t name_len)
-{
-	return ast_channel_iterator_new(ao2_flags, name, name_len, NULL, NULL);
-}
-
-struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags)
-{
-	return ast_channel_iterator_new(ao2_flags, NULL, 0, NULL, NULL);
-}
-
-/*!
- * \note This function will be reduced to 1 line of code once ao2 supports
- * returning multiple objects from an ao2_callback() using OBJ_MULTIPLE.
- */
+}
+
+struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context)
+{
+	return channel_iterator_search(NULL, 0, exten, context);
+}
+
+struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name, size_t name_len)
+{
+	return channel_iterator_search(name, name_len, NULL, NULL);
+}
+
+struct ast_channel_iterator *ast_channel_iterator_all_new(void)
+{
+	struct ast_channel_iterator *i;
+
+	if (!(i = ast_calloc(1, sizeof(*i)))) {
+		return NULL;
+	}
+
+	i->simple_iterator = ao2_iterator_init(channels, 0);
+	i->active_iterator = &i->simple_iterator;
+
+	return i;
+}
+
 struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i)
 {
-	struct ast_channel *chan = NULL;
-
-	for (; (chan = ao2_iterator_next(&i->i));
-			ast_channel_unlock(chan), ast_channel_unref(chan)) {
-
-		ast_channel_lock(chan);
-
-		if (i->name) { /* match by name */
-			if (!i->name_len) {
-				if (strcasecmp(chan->name, i->name) && strcasecmp(chan->uniqueid, i->name)) {
-					continue; /* name match failed */
-				}
-			} else {
-				if (strncasecmp(chan->name, i->name, i->name_len) &&
-						strncasecmp(chan->uniqueid, i->name, i->name_len)) {
-					continue; /* name match failed */
-				}
-			}
-		} else if (i->exten) {
-			if (i->context && strcasecmp(chan->context, i->context) &&
-					strcasecmp(chan->macrocontext, i->context)) {
-				continue; /* context match failed */
-			}
-
-			if (strcasecmp(chan->exten, i->exten) &&
-					strcasecmp(chan->macroexten, i->exten)) {
-				continue; /* exten match failed */
-			}
-		}
-
-		ast_channel_unlock(chan);
-
-		break; /* chan points to the next chan desired. */
-	}
-
-	return chan;
+	return ao2_iterator_next(i->active_iterator);
 }
 
 static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
@@ -1407,7 +1353,7 @@
 }
 
 static struct ast_channel *ast_channel_get_full(const char *name, size_t name_len,
-	const char *exten, const char *context)
+						const char *exten, const char *context)
 {
 	struct ast_channel tmp_chan = {
 		.name = name,

Modified: trunk/main/cli.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/cli.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/main/cli.c (original)
+++ trunk/main/cli.c Wed Oct 21 16:08:47 2009
@@ -827,7 +827,7 @@
 				"CallerID", "Duration", "Accountcode", "PeerAccount", "BridgedTo");
 	}
 
-	if (!count && !(iter = ast_channel_iterator_all_new(0))) {
+	if (!count && !(iter = ast_channel_iterator_all_new())) {
 		return CLI_FAILURE;
 	}
 
@@ -1454,7 +1454,7 @@
 		return NULL;
 	}
 
-	if (!(iter = ast_channel_iterator_by_name_new(0, word, strlen(word)))) {
+	if (!(iter = ast_channel_iterator_by_name_new(word, strlen(word)))) {
 		return NULL;
 	}
 
@@ -1466,6 +1466,8 @@
 		}
 		ast_channel_unref(c);
 	}
+
+	ast_channel_iterator_destroy(iter);
 
 	return ret == &notfound ? NULL : ret;
 }

Modified: trunk/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/manager.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/main/manager.c (original)
+++ trunk/main/manager.c Wed Oct 21 16:08:47 2009
@@ -2806,7 +2806,7 @@
 	}
 
 	if (all) {
-		if (!(iter = ast_channel_iterator_all_new(0))) {
+		if (!(iter = ast_channel_iterator_all_new())) {
 			ast_free(str);
 			astman_send_error(s, m, "Memory Allocation Failure");
 			return 1;
@@ -2914,6 +2914,10 @@
 		}
 	}
 
+	if (iter) {
+		ast_channel_iterator_destroy(iter);
+	}
+
 	astman_append(s,
 		"Event: StatusComplete\r\n"
 		"%s"
@@ -3643,7 +3647,7 @@
 		idText[0] = '\0';
 	}
 
-	if (!(iter = ast_channel_iterator_all_new(0))) {
+	if (!(iter = ast_channel_iterator_all_new())) {
 		astman_send_error(s, m, "Memory Allocation Failure");
 		return 1;
 	}

Modified: trunk/res/snmp/agent.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/snmp/agent.c?view=diff&rev=225244&r1=225243&r2=225244
==============================================================================
--- trunk/res/snmp/agent.c (original)
+++ trunk/res/snmp/agent.c Wed Oct 21 16:08:47 2009
@@ -243,7 +243,7 @@
 
 	i = name[*length - 1] - 1;
 
-	if (!(iter = ast_channel_iterator_all_new(0))) {
+	if (!(iter = ast_channel_iterator_all_new())) {
 		return NULL;
 	}
 
@@ -588,7 +588,7 @@
 
 		long_ret = 0;
 
-		if (!(iter = ast_channel_iterator_all_new(0))) {
+		if (!(iter = ast_channel_iterator_all_new())) {
 			return NULL;
 		}
 
@@ -622,7 +622,7 @@
 		return NULL;
 	}
 
-	if (!(iter = ast_channel_iterator_all_new(0))) {
+	if (!(iter = ast_channel_iterator_all_new())) {
 		return NULL;
 	}
 
@@ -634,6 +634,8 @@
 		ast_channel_unlock(chan);
 		chan = ast_channel_unref(chan);
 	}
+
+	ast_channel_iterator_destroy(iter);
 
 	*var_len = sizeof(long_ret);
 




More information about the svn-commits mailing list