aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-21 21:08:47 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2009-10-21 21:08:47 +0000
commit4f428997ca5d8e9ee1023c09cd4109e0823817b4 (patch)
treefc090fae29428e50ebaebee71709d20ea2681aee
parent02992ab88835322a8f97bd9f26ddde84c43e91d3 (diff)
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/ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@225244 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--apps/app_chanspy.c6
-rw-r--r--apps/app_directed_pickup.c4
-rw-r--r--apps/app_softhangup.c2
-rw-r--r--funcs/func_channel.c2
-rw-r--r--include/asterisk/astobj2.h58
-rw-r--r--include/asterisk/channel.h12
-rw-r--r--include/asterisk/lock.h1
-rw-r--r--main/astobj2.c109
-rw-r--r--main/channel.c138
-rw-r--r--main/cli.c6
-rw-r--r--main/manager.c8
-rw-r--r--res/snmp/agent.c8
12 files changed, 170 insertions, 184 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c
index c781f37a6..ad5ed7013 100644
--- a/apps/app_chanspy.c
+++ b/apps/app_chanspy.c
@@ -786,11 +786,11 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
/* 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) {
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index a6ca09ac5..bc25defe2 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -210,7 +210,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
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;
}
@@ -223,6 +223,8 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
target = ast_channel_unref(target);
}
+ ast_channel_iterator_destroy(iter);
+
if (target) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
diff --git a/apps/app_softhangup.c b/apps/app_softhangup.c
index 50bdb6809..3513bb775 100644
--- a/apps/app_softhangup.c
+++ b/apps/app_softhangup.c
@@ -94,7 +94,7 @@ static int softhangup_exec(struct ast_channel *chan, const char *data)
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;
}
diff --git a/funcs/func_channel.c b/funcs/func_channel.c
index e82c39a51..f20bfcaa1 100644
--- a/funcs/func_channel.c
+++ b/funcs/func_channel.c
@@ -465,7 +465,7 @@ static int func_channels_read(struct ast_channel *chan, const char *function, ch
}
}
- if (!(iter = ast_channel_iterator_all_new(0))) {
+ if (!(iter = ast_channel_iterator_all_new())) {
if (!ast_strlen_zero(data)) {
regfree(&re);
}
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index f0393d34f..6caa4a7c4 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -18,6 +18,7 @@
#define _ASTERISK_ASTOBJ2_H
#include "asterisk/compat.h"
+#include "asterisk/linkedlists.h"
/*! \file
* \ref AstObj2
@@ -547,7 +548,7 @@ Operations on container include:
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 @@ Operations on container include:
- 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 _cb_results {
*/
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
@@ -817,12 +817,6 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *obj, char *tag, char *fi
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 */
-};
-
/*@} */
/*! \brief
@@ -847,21 +841,22 @@ struct ao2_list {
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 @@ struct ao2_list {
* 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,13 +885,9 @@ struct ao2_list {
* 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 @@ enum ao2_iterator_flags {
* 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),
};
/*!
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index cab334685..2b285ba8d 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2210,7 +2210,6 @@ struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_ite
/*!
* \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 @@ struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_ite
*
* \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,14 +2241,11 @@ struct ast_channel_iterator *ast_channel_iterator_by_exten_new(int ao2_flags, co
*
* \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 @@ struct ast_channel_iterator *ast_channel_iterator_by_name_new(int ao2_flags, con
*
* \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
diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h
index bfbed1e6f..4785a7636 100644
--- a/include/asterisk/lock.h
+++ b/include/asterisk/lock.h
@@ -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.
diff --git a/main/astobj2.c b/main/astobj2.c
index 01fd4b17f..cecef7c66 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -292,7 +292,7 @@ static int internal_ao2_ref(void *user_data, const int delta)
* 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 @@ static void *internal_ao2_callback(struct ao2_container *c,
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 @@ static void *internal_ao2_callback(struct ao2_container *c,
}
} 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 @@ static void *internal_ao2_callback(struct ao2_container *c,
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 (flags & OBJ_UNLINK) { /* must unlink */
- struct bucket_list *x = cur;
+ /* 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 */
/* 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 @@ static void *internal_ao2_callback(struct ao2_container *c,
}
}
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 @@ struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
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 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_li
/* 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 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_li
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;
diff --git a/main/channel.c b/main/channel.c
index 60ad9638b..af904692a 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1234,137 +1234,83 @@ struct ast_channel *ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg,
}
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 (exten) {
+ ast_copy_string(tmp_chan.exten, exten, sizeof(tmp_chan.exten));
}
- if (!ast_strlen_zero(context) && !(i->context = ast_strdup(context))) {
- goto return_error;
+ if (context) {
+ ast_copy_string(tmp_chan.context, context, sizeof(tmp_chan.context));
}
- if (!ast_strlen_zero(name) && !(i->name = ast_strdup(name))) {
- goto return_error;
+ 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;
}
- i->name_len = name_len;
-
- i->i = ao2_iterator_init(channels, ao2_flags);
-
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)
+struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context)
{
- return ast_channel_iterator_new(ao2_flags, name, name_len, NULL, NULL);
+ return channel_iterator_search(NULL, 0, exten, context);
}
-struct ast_channel_iterator *ast_channel_iterator_all_new(int ao2_flags)
+struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name, size_t name_len)
{
- return ast_channel_iterator_new(ao2_flags, NULL, 0, NULL, NULL);
+ return channel_iterator_search(name, name_len, 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 *ast_channel_iterator_next(struct ast_channel_iterator *i)
+struct ast_channel_iterator *ast_channel_iterator_all_new(void)
{
- 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 */
- }
+ struct ast_channel_iterator *i;
- if (strcasecmp(chan->exten, i->exten) &&
- strcasecmp(chan->macroexten, i->exten)) {
- continue; /* exten match failed */
- }
- }
+ if (!(i = ast_calloc(1, sizeof(*i)))) {
+ return NULL;
+ }
- ast_channel_unlock(chan);
+ i->simple_iterator = ao2_iterator_init(channels, 0);
+ i->active_iterator = &i->simple_iterator;
- break; /* chan points to the next chan desired. */
- }
+ return i;
+}
- return chan;
+struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i)
+{
+ return ao2_iterator_next(i->active_iterator);
}
static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
@@ -1407,7 +1353,7 @@ static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
}
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,
diff --git a/main/cli.c b/main/cli.c
index 5b31bba2b..abfc8f0a9 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -827,7 +827,7 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
"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 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta
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;
}
@@ -1467,6 +1467,8 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta
ast_channel_unref(c);
}
+ ast_channel_iterator_destroy(iter);
+
return ret == &notfound ? NULL : ret;
}
diff --git a/main/manager.c b/main/manager.c
index 1bd2eaeb4..a02d06106 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -2806,7 +2806,7 @@ static int action_status(struct mansession *s, const struct message *m)
}
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 @@ static int action_status(struct mansession *s, const struct message *m)
}
}
+ if (iter) {
+ ast_channel_iterator_destroy(iter);
+ }
+
astman_append(s,
"Event: StatusComplete\r\n"
"%s"
@@ -3643,7 +3647,7 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m
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;
}
diff --git a/res/snmp/agent.c b/res/snmp/agent.c
index f4d4fc6fd..df4523339 100644
--- a/res/snmp/agent.c
+++ b/res/snmp/agent.c
@@ -243,7 +243,7 @@ static u_char *ast_var_channels_table(struct variable *vp, oid *name, size_t *le
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 @@ static u_char *ast_var_channel_types_table(struct variable *vp, oid *name, size_
long_ret = 0;
- if (!(iter = ast_channel_iterator_all_new(0))) {
+ if (!(iter = ast_channel_iterator_all_new())) {
return NULL;
}
@@ -622,7 +622,7 @@ static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *le
return NULL;
}
- if (!(iter = ast_channel_iterator_all_new(0))) {
+ if (!(iter = ast_channel_iterator_all_new())) {
return NULL;
}
@@ -635,6 +635,8 @@ static u_char *ast_var_channel_bridge(struct variable *vp, oid *name, size_t *le
chan = ast_channel_unref(chan);
}
+ ast_channel_iterator_destroy(iter);
+
*var_len = sizeof(long_ret);
return (vp->magic == ASTCHANBRIDGECOUNT) ? (u_char *) &long_ret : NULL;