aboutsummaryrefslogtreecommitdiffstats
path: root/main/channel.c
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 /main/channel.c
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
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c138
1 files changed, 42 insertions, 96 deletions
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,