[asterisk-commits] dlee: branch dlee/hashtab-skiplist r399768 - in /team/dlee/hashtab-skiplist: ...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Sep 24 18:39:59 CDT 2013
Author: dlee
Date: Tue Sep 24 18:39:56 2013
New Revision: 399768
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=399768
Log:
Merged revisions 399752-399764 from http://svn.asterisk.org/svn/asterisk/team/group/performance
Modified:
team/dlee/hashtab-skiplist/ (props changed)
team/dlee/hashtab-skiplist/apps/app_queue.c
team/dlee/hashtab-skiplist/channels/chan_iax2.c
team/dlee/hashtab-skiplist/main/astobj2.c
team/dlee/hashtab-skiplist/main/cdr.c
team/dlee/hashtab-skiplist/main/stasis_bridges.c
team/dlee/hashtab-skiplist/tests/test_cdr.c
Propchange: team/dlee/hashtab-skiplist/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.
Propchange: team/dlee/hashtab-skiplist/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Sep 24 18:39:56 2013
@@ -1,1 +1,1 @@
-/team/group/performance:1-399750
+/team/group/performance:1-399767
Modified: team/dlee/hashtab-skiplist/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/hashtab-skiplist/apps/app_queue.c?view=diff&rev=399768&r1=399767&r2=399768
==============================================================================
--- team/dlee/hashtab-skiplist/apps/app_queue.c (original)
+++ team/dlee/hashtab-skiplist/apps/app_queue.c Tue Sep 24 18:39:56 2013
@@ -5914,6 +5914,8 @@
const char *monitor_options;
const char *monitor_exec;
+ escaped_monitor_exec[0] = '\0';
+
if (filename) {
escape_and_substitute(qe->chan, filename, escaped_filename, sizeof(escaped_filename));
} else {
Modified: team/dlee/hashtab-skiplist/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/hashtab-skiplist/channels/chan_iax2.c?view=diff&rev=399768&r1=399767&r2=399768
==============================================================================
--- team/dlee/hashtab-skiplist/channels/chan_iax2.c (original)
+++ team/dlee/hashtab-skiplist/channels/chan_iax2.c Tue Sep 24 18:39:56 2013
@@ -5517,34 +5517,44 @@
break;
}
other = (who == c0) ? c1 : c0; /* the 'other' channel */
- if ((f->frametype == AST_FRAME_CONTROL)) {
- if (f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
+ if (f->frametype == AST_FRAME_CONTROL) {
+ switch (f->subclass.integer) {
+ case AST_CONTROL_VIDUPDATE:
+ case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_SRCCHANGE:
+ case AST_CONTROL_T38_PARAMETERS:
+ ast_write(other, f);
+ break;
+ case AST_CONTROL_PVT_CAUSE_CODE:
ast_channel_hangupcause_hash_set(other, f->data.ptr, f->datalen);
- } else if (f->subclass.integer != AST_CONTROL_SRCUPDATE) {
+ break;
+ default:
*fo = f;
*rc = who;
- res = AST_BRIDGE_COMPLETE;
+ res = AST_BRIDGE_COMPLETE;
break;
}
- }
- if ((f->frametype == AST_FRAME_VOICE) ||
- (f->frametype == AST_FRAME_TEXT) ||
- (f->frametype == AST_FRAME_VIDEO) ||
- (f->frametype == AST_FRAME_IMAGE) ||
- (f->frametype == AST_FRAME_DTMF) ||
- (f->frametype == AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_PVT_CAUSE_CODE)) {
+ if (res == AST_BRIDGE_COMPLETE) {
+ break;
+ }
+ } else if (f->frametype == AST_FRAME_VOICE
+ || f->frametype == AST_FRAME_TEXT
+ || f->frametype == AST_FRAME_VIDEO
+ || f->frametype == AST_FRAME_IMAGE) {
+ ast_write(other, f);
+ } else if (f->frametype == AST_FRAME_DTMF) {
/* monitored dtmf take out of the bridge.
* check if we monitor the specific source.
*/
int monitored_source = (who == c0) ? AST_BRIDGE_DTMF_CHANNEL_0 : AST_BRIDGE_DTMF_CHANNEL_1;
- if (f->frametype == AST_FRAME_DTMF && (flags & monitored_source)) {
+
+ if (flags & monitored_source) {
*rc = who;
*fo = f;
res = AST_BRIDGE_COMPLETE;
/* Remove from native mode */
break;
}
- /* everything else goes to the other side */
ast_write(other, f);
}
ast_frfree(f);
Modified: team/dlee/hashtab-skiplist/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/hashtab-skiplist/main/astobj2.c?view=diff&rev=399768&r1=399767&r2=399768
==============================================================================
--- team/dlee/hashtab-skiplist/main/astobj2.c (original)
+++ team/dlee/hashtab-skiplist/main/astobj2.c Tue Sep 24 18:39:56 2013
@@ -1175,7 +1175,8 @@
return NULL;
}
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ flags &= ~OBJ_SEARCH_MASK;
+ flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
__ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
return NULL;
@@ -1189,7 +1190,8 @@
return NULL;
}
- flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
+ flags &= ~OBJ_SEARCH_MASK;
+ flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
__ao2_callback(c, flags, ao2_match_by_addr, user_data);
return NULL;
@@ -2132,7 +2134,7 @@
return NULL;
}
- i = abs(self->hash_fn(obj_new, OBJ_POINTER));
+ i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT));
i %= self->n_buckets;
if (tag) {
@@ -2177,7 +2179,7 @@
if (options & AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN) {
if (sort_fn) {
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp > 0) {
continue;
}
@@ -2209,7 +2211,7 @@
} else {
if (sort_fn) {
AST_DLLIST_TRAVERSE_SAFE_BEGIN(&bucket->list, cur, links) {
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp < 0) {
continue;
}
@@ -2309,15 +2311,24 @@
* If lookup by pointer or search key, run the hash and optional
* sort functions. Otherwise, traverse the whole container.
*/
- if (flags & (OBJ_POINTER | OBJ_KEY)) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ case OBJ_SEARCH_KEY:
/* we know hash can handle this case */
- bucket_cur = abs(self->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)));
+ bucket_cur = abs(self->hash_fn(arg, flags & OBJ_SEARCH_MASK));
bucket_cur %= self->n_buckets;
state->sort_fn = self->common.sort_fn;
- } else {
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ /* scan all buckets for partial key matches */
+ bucket_cur = -1;
+ state->sort_fn = self->common.sort_fn;
+ break;
+ default:
/* don't know, let's scan all buckets */
bucket_cur = -1;
- state->sort_fn = (flags & OBJ_PARTIAL_KEY) ? self->common.sort_fn : NULL;
+ state->sort_fn = NULL;
+ break;
}
if (state->descending) {
@@ -2353,8 +2364,7 @@
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp > 0) {
continue;
}
@@ -2379,7 +2389,7 @@
/* Was this the starting bucket? */
if (bucket_cur == state->bucket_start
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* In case the bucket was empty or none of the nodes matched. */
state->sort_fn = NULL;
}
@@ -2387,7 +2397,7 @@
/* Was this the first container bucket? */
if (bucket_cur == 0
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the end to ensure we check every bucket */
bucket_cur = self->n_buckets;
state->bucket_last = state->bucket_start + 1;
@@ -2434,8 +2444,7 @@
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp < 0) {
continue;
}
@@ -2460,7 +2469,7 @@
/* Was this the starting bucket? */
if (bucket_cur == state->bucket_start
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* In case the bucket was empty or none of the nodes matched. */
state->sort_fn = NULL;
}
@@ -2468,7 +2477,7 @@
/* Was this the last container bucket? */
if (bucket_cur == self->n_buckets - 1
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the beginning to ensure we check every bucket */
bucket_cur = -1;
state->bucket_last = state->bucket_start;
@@ -2541,8 +2550,7 @@
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp > 0) {
continue;
}
@@ -2573,7 +2581,7 @@
/* Was this the first container bucket? */
if (bucket_cur == 0
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the end to ensure we check every bucket */
bucket_cur = self->n_buckets;
state->bucket_last = state->bucket_start + 1;
@@ -2608,8 +2616,7 @@
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp < 0) {
continue;
}
@@ -2640,7 +2647,7 @@
/* Was this the last container bucket? */
if (bucket_cur == self->n_buckets - 1
&& (flags & OBJ_CONTINUE)
- && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
+ && (flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_NONE) {
/* Move to the beginning to ensure we check every bucket */
bucket_cur = -1;
state->bucket_last = state->bucket_start;
@@ -3042,7 +3049,7 @@
++count_obj;
/* Check container hash key for expected bucket. */
- bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_POINTER));
+ bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_SEARCH_OBJECT));
bucket_exp %= self->n_buckets;
if (bucket != bucket_exp) {
ast_log(LOG_ERROR, "Bucket %d node hashes to bucket %d!\n",
@@ -3053,7 +3060,7 @@
/* Check sort if configured. */
if (self->common.sort_fn) {
if (obj_last
- && self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+ && self->common.sort_fn(obj_last, node->common.obj, OBJ_SEARCH_OBJECT) > 0) {
ast_log(LOG_ERROR, "Bucket %d nodes out of sorted order!\n",
bucket);
return -1;
@@ -3509,9 +3516,9 @@
* \param sort_fn Sort comparison function for non-empty nodes.
* \param obj_right pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
- * OBJ_POINTER - if set, 'obj_right', is an object.
- * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
- * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
+ * OBJ_SEARCH_OBJECT - if set, 'obj_right', is an object.
+ * OBJ_SEARCH_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_SEARCH_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
* \param bias How to bias search direction for duplicates
*
* \return enum empty_node_direction to proceed.
@@ -4259,7 +4266,7 @@
for (;;) {
if (!cur->common.obj) {
/* Which direction do we go to insert this node? */
- if (rb_find_empty_direction(cur, sort_fn, node->common.obj, OBJ_POINTER, bias)
+ if (rb_find_empty_direction(cur, sort_fn, node->common.obj, OBJ_SEARCH_OBJECT, bias)
== GO_LEFT) {
if (cur->left) {
cur = cur->left;
@@ -4283,7 +4290,7 @@
rb_insert_fixup(self, node);
return AO2_CONTAINER_INSERT_NODE_INSERTED;
}
- cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp > 0) {
if (cur->left) {
cur = cur->left;
@@ -4365,7 +4372,7 @@
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
@@ -4381,7 +4388,7 @@
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
@@ -4406,7 +4413,7 @@
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
@@ -4422,7 +4429,7 @@
/* Reject inserting the same object */
return AO2_CONTAINER_INSERT_NODE_REJECTED;
}
- cmp = sort_fn(next->common.obj, node->common.obj, OBJ_POINTER);
+ cmp = sort_fn(next->common.obj, node->common.obj, OBJ_SEARCH_OBJECT);
if (cmp) {
break;
}
@@ -4543,8 +4550,7 @@
if (state->sort_fn) {
/* Filter node through the sort_fn */
- cmp = state->sort_fn(node->common.obj, arg,
- flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
+ cmp = state->sort_fn(node->common.obj, arg, flags & OBJ_SEARCH_MASK);
if (cmp) {
/* No more nodes in this container are possible to match. */
break;
@@ -4580,9 +4586,9 @@
* \param self Container to operate upon.
* \param obj_right pointer to the (user-defined part) of an object.
* \param flags flags from ao2_callback()
- * OBJ_POINTER - if set, 'obj_right', is an object.
- * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
- * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
+ * OBJ_SEARCH_OBJECT - if set, 'obj_right', is an object.
+ * OBJ_SEARCH_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_SEARCH_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
* OBJ_CONTINUE - if set, return node right before or right after search key if not a match.
* \param bias How to bias search direction for duplicates
*
@@ -4597,7 +4603,7 @@
struct rbtree_node *next = NULL;
ao2_sort_fn *sort_fn;
- sort_flags = flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY);
+ sort_flags = flags & OBJ_SEARCH_MASK;
sort_fn = self->common.sort_fn;
/* Find node where normal search would find it. */
@@ -4730,12 +4736,17 @@
state->arg = arg;
state->flags = flags;
- if (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ case OBJ_SEARCH_KEY:
+ case OBJ_SEARCH_PARTIAL_KEY:
/* We are asked to do a directed search. */
state->sort_fn = self->common.sort_fn;
- } else {
+ break;
+ default:
/* Don't know, let's visit all nodes */
state->sort_fn = NULL;
+ break;
}
if (!self->root) {
@@ -4763,7 +4774,7 @@
switch (self->common.options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
- if ((flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) != OBJ_PARTIAL_KEY) {
+ if ((flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_PARTIAL_KEY) {
/* There are no duplicates allowed. */
bias = BIAS_EQUAL;
break;
@@ -4798,7 +4809,7 @@
switch (self->common.options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
- if ((flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) != OBJ_PARTIAL_KEY) {
+ if ((flags & OBJ_SEARCH_MASK) != OBJ_SEARCH_PARTIAL_KEY) {
/* There are no duplicates allowed. */
bias = BIAS_EQUAL;
break;
@@ -5228,7 +5239,7 @@
}
if (obj_last) {
- if (self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
+ if (self->common.sort_fn(obj_last, node->common.obj, OBJ_SEARCH_OBJECT) > 0) {
ast_log(LOG_ERROR, "Tree nodes are out of sorted order!\n");
return -1;
}
@@ -5517,18 +5528,33 @@
const struct ao2_reg_container *reg_left = obj_left;
int cmp;
- if (flags & OBJ_KEY) {
- const char *name = obj_right;
-
- cmp = strcasecmp(reg_left->name, name);
- } else if (flags & OBJ_PARTIAL_KEY) {
- const struct ao2_reg_partial_key *partial_key = obj_right;
-
- cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
- } else {
- const struct ao2_reg_container *reg_right = obj_right;
-
- cmp = strcasecmp(reg_left->name, reg_right->name);
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ {
+ const struct ao2_reg_container *reg_right = obj_right;
+
+ cmp = strcasecmp(reg_left->name, reg_right->name);
+ }
+ break;
+ case OBJ_SEARCH_KEY:
+ {
+ const char *name = obj_right;
+
+ cmp = strcasecmp(reg_left->name, name);
+ }
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ {
+ const struct ao2_reg_partial_key *partial_key = obj_right;
+
+ cmp = strncasecmp(reg_left->name, partial_key->name, partial_key->len);
+ }
+ break;
+ default:
+ /* Sort can only work on something with a full or partial key. */
+ ast_assert(0);
+ cmp = 0;
+ break;
}
return cmp;
}
@@ -5575,7 +5601,7 @@
void ao2_container_unregister(const char *name)
{
#if defined(AST_DEVMODE)
- ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_KEY,
+ ao2_t_find(reg_containers, name, OBJ_UNLINK | OBJ_NODATA | OBJ_SEARCH_KEY,
"Unregister container");
#endif /* defined(AST_DEVMODE) */
}
@@ -5606,7 +5632,7 @@
partial_key.name = a->word;
which.find_nth = a->n;
which.count = 0;
- reg = ao2_t_callback_data(reg_containers, partial_key.len ? OBJ_PARTIAL_KEY : 0,
+ reg = ao2_t_callback_data(reg_containers, partial_key.len ? OBJ_SEARCH_PARTIAL_KEY : 0,
ao2_complete_reg_cb, &partial_key, &which, "Find partial registered container");
if (reg) {
name = ast_strdup(reg->name);
@@ -5675,7 +5701,7 @@
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ao2_container_dump(reg->registered, 0, name, (void *) &a->fd, cli_output,
reg->prnt_obj);
@@ -5711,7 +5737,7 @@
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ao2_container_stats(reg->registered, 0, name, (void *) &a->fd, cli_output);
ao2_t_ref(reg, -1, "Done with registered container object.");
@@ -5746,7 +5772,7 @@
}
name = a->argv[3];
- reg = ao2_t_find(reg_containers, name, OBJ_KEY, "Find registered container");
+ reg = ao2_t_find(reg_containers, name, OBJ_SEARCH_KEY, "Find registered container");
if (reg) {
ast_cli(a->fd, "Container check of '%s': %s.\n", name,
ao2_container_check(reg->registered, 0) ? "failed" : "OK");
Modified: team/dlee/hashtab-skiplist/main/cdr.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/hashtab-skiplist/main/cdr.c?view=diff&rev=399768&r1=399767&r2=399768
==============================================================================
--- team/dlee/hashtab-skiplist/main/cdr.c (original)
+++ team/dlee/hashtab-skiplist/main/cdr.c Tue Sep 24 18:39:56 2013
@@ -327,7 +327,7 @@
AST_MUTEX_DEFINE_STATIC(cdr_pending_lock);
static ast_cond_t cdr_pending_cond;
-/*! \brief A container of the active CDRs indexed by Party A channel name */
+/*! \brief A container of the active CDRs indexed by Party A channel id */
static struct ao2_container *active_cdrs_by_channel;
/*! \brief Message router for stasis messages regarding channel state */
@@ -682,6 +682,7 @@
struct ast_flags flags; /*!< Flags on the CDR */
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(linkedid); /*!< Linked ID. Cached here as it may change out from party A, which must be immutable */
+ AST_STRING_FIELD(uniqueid); /*!< Unique id of party A. Cached here as it is the primary key of this CDR */
AST_STRING_FIELD(name); /*!< Channel name of party A. Cached here as the party A address may change */
AST_STRING_FIELD(bridge); /*!< The bridge the party A happens to be in. */
AST_STRING_FIELD(appl); /*!< The last accepted application party A was in */
@@ -772,42 +773,58 @@
}
}
/*! \internal
- * \brief Hash function for containers of CDRs indexing by Party A name */
+ * \brief Hash function for containers of CDRs indexing by Party A uniqueid */
static int cdr_object_channel_hash_fn(const void *obj, const int flags)
{
- const struct cdr_object *cdr = obj;
- const char *name = (flags & OBJ_KEY) ? obj : cdr->name;
- return ast_str_case_hash(name);
+ const struct cdr_object *cdr;
+ const char *key;
+
+ switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+ case OBJ_KEY:
+ key = obj;
+ break;
+ case OBJ_POINTER:
+ cdr = obj;
+ key = cdr->uniqueid;
+ break;
+ default:
+ ast_assert(0);
+ return 0;
+ }
+ return ast_str_case_hash(key);
}
/*! \internal
- * \brief Comparison function for containers of CDRs indexing by Party A name
+ * \brief Comparison function for containers of CDRs indexing by Party A uniqueid
*/
static int cdr_object_channel_cmp_fn(void *obj, void *arg, int flags)
{
- struct cdr_object *left = obj;
- struct cdr_object *right = arg;
- const char *match = (flags & OBJ_KEY) ? arg : right->name;
- return strcasecmp(left->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
-}
-
-/*! \internal
- * \brief Comparison function for containers of CDRs indexing by bridge. Note
- * that we expect there to be collisions, as a single bridge may have multiple
- * CDRs active at one point in time
- */
-static int cdr_object_bridge_cmp_fn(void *obj, void *arg, int flags)
-{
- struct cdr_object *left = obj;
- struct cdr_object *it_cdr;
- const char *match = arg;
-
- for (it_cdr = left; it_cdr; it_cdr = it_cdr->next) {
- if (!strcasecmp(it_cdr->bridge, match)) {
- return CMP_MATCH;
- }
- }
- return 0;
+ struct cdr_object *left = obj;
+ struct cdr_object *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+ case OBJ_POINTER:
+ right_key = right->uniqueid;
+ /* Fall through */
+ case OBJ_KEY:
+ cmp = strcmp(left->uniqueid, right_key);
+ break;
+ case OBJ_PARTIAL_KEY:
+ /*
+ * We could also use a partial key struct containing a length
+ * so strlen() does not get called for every comparison instead.
+ */
+ cmp = strncmp(left->uniqueid, right_key, strlen(right_key));
+ break;
+ default:
+ /* Sort can only work on something with a full or partial key. */
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ return cmp ? 0 : CMP_MATCH;
}
/*!
@@ -854,6 +871,7 @@
ao2_cleanup(cdr);
return NULL;
}
+ ast_string_field_set(cdr, uniqueid, chan->uniqueid);
ast_string_field_set(cdr, name, chan->name);
ast_string_field_set(cdr, linkedid, chan->linkedid);
cdr->disposition = AST_CDR_NULL;
@@ -985,7 +1003,7 @@
} else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
return right;
} else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
- return right;
+ return right;
} else {
/* Okay, fine, take the left one */
return left;
@@ -1062,12 +1080,15 @@
struct ast_var_t *it_var, *it_copy_var;
struct ast_channel_snapshot *party_a;
struct ast_channel_snapshot *party_b;
+ RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
struct ast_cdr *cdr_copy;
/* Don't create records for CDRs where the party A was a dialed channel */
- if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
+ if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
+ CDR_DEBUG(mod_cfg, "%p - %s is dialed and has no Party B; discarding\n", it_cdr,
+ it_cdr->party_a.snapshot->name);
continue;
}
@@ -1437,6 +1458,7 @@
static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
struct cdr_object *cand_cdr)
{
+ RAII_VAR(struct module_config *, mod_cfg, ao2_global_obj_ref(module_configs), ao2_cleanup);
struct cdr_object_snapshot *party_a;
/* Don't match on ourselves */
@@ -1447,6 +1469,8 @@
/* Try the candidate CDR's Party A first */
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
+ CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
+ cdr, cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name);
cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
if (!cand_cdr->party_b.snapshot) {
/* We just stole them - finalize their CDR. Note that this won't
@@ -1465,6 +1489,8 @@
}
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
+ CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
+ cdr, cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name);
cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
return 0;
}
@@ -1474,27 +1500,31 @@
static enum process_bridge_enter_results single_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
{
- struct ao2_iterator *it_cdrs;
- struct cdr_object *cand_cdr_master;
- char *bridge_id = ast_strdupa(bridge->uniqueid);
+ struct ao2_iterator it_cdrs;
+ char *channel_id;
int success = 0;
ast_string_field_set(cdr, bridge, bridge->uniqueid);
- /* Get parties in the bridge */
- it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
- cdr_object_bridge_cmp_fn, bridge_id);
- if (!it_cdrs) {
- /* No one in the bridge yet! */
+ if (ao2_container_count(bridge->channels) == 1) {
+ /* No one in the bridge yet but us! */
cdr_object_transition_state(cdr, &bridge_state_fn_table);
return BRIDGE_ENTER_ONLY_PARTY;
}
- while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
+ for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
+ !success && (channel_id = ao2_iterator_next(&it_cdrs));
+ ao2_ref(channel_id, -1)) {
+ RAII_VAR(struct cdr_object *, cand_cdr_master,
+ ao2_find(active_cdrs_by_channel, channel_id, OBJ_KEY),
+ ao2_cleanup);
struct cdr_object *cand_cdr;
- RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
- SCOPED_AO2LOCK(lock, cand_cdr_master);
-
+
+ if (!cand_cdr_master) {
+ continue;
+ }
+
+ ao2_lock(cand_cdr_master);
for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
/* Skip any records that are not in a bridge or in this bridge.
* I'm not sure how that would happen, but it pays to be careful. */
@@ -1510,8 +1540,9 @@
success = 1;
break;
}
- }
- ao2_iterator_destroy(it_cdrs);
+ ao2_unlock(cand_cdr_master);
+ }
+ ao2_iterator_destroy(&it_cdrs);
/* We always transition state, even if we didn't get a peer */
cdr_object_transition_state(cdr, &bridge_state_fn_table);
@@ -1620,27 +1651,32 @@
static enum process_bridge_enter_results dial_state_process_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
{
- struct ao2_iterator *it_cdrs;
- char *bridge_id = ast_strdupa(bridge->uniqueid);
- struct cdr_object *cand_cdr_master;
+ struct ao2_iterator it_cdrs;
+ char *channel_id;
int success = 0;
ast_string_field_set(cdr, bridge, bridge->uniqueid);
/* Get parties in the bridge */
- it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
- cdr_object_bridge_cmp_fn, bridge_id);
- if (!it_cdrs) {
- /* No one in the bridge yet! */
+ if (ao2_container_count(bridge->channels) == 1) {
+ /* No one in the bridge yet but us! */
cdr_object_transition_state(cdr, &bridge_state_fn_table);
return BRIDGE_ENTER_ONLY_PARTY;
}
- while ((cand_cdr_master = ao2_iterator_next(it_cdrs))) {
+ for (it_cdrs = ao2_iterator_init(bridge->channels, 0);
+ !success && (channel_id = ao2_iterator_next(&it_cdrs));
+ ao2_ref(channel_id, -1)) {
+ RAII_VAR(struct cdr_object *, cand_cdr_master,
+ ao2_find(active_cdrs_by_channel, channel_id, OBJ_KEY),
+ ao2_cleanup);
struct cdr_object *cand_cdr;
- RAII_VAR(struct cdr_object *, cdr_cleanup, cand_cdr_master, ao2_cleanup);
- SCOPED_AO2LOCK(lock, cand_cdr_master);
-
+
+ if (!cand_cdr_master) {
+ continue;
+ }
+
+ ao2_lock(cand_cdr_master);
for (cand_cdr = cand_cdr_master; cand_cdr; cand_cdr = cand_cdr->next) {
/* Skip any records that are not in a bridge or in this bridge.
* I'm not sure how that would happen, but it pays to be careful. */
@@ -1669,8 +1705,9 @@
success = 1;
break;
}
- }
- ao2_iterator_destroy(it_cdrs);
+ ao2_unlock(cand_cdr_master);
+ }
+ ao2_iterator_destroy(&it_cdrs);
/* We always transition state, even if we didn't get a peer */
cdr_object_transition_state(cdr, &bridge_state_fn_table);
@@ -1829,9 +1866,9 @@
/* Figure out who is running this show */
if (caller) {
- cdr = ao2_find(active_cdrs_by_channel, caller->name, OBJ_KEY);
+ cdr = ao2_find(active_cdrs_by_channel, caller->uniqueid, OBJ_KEY);
} else {
- cdr = ao2_find(active_cdrs_by_channel, peer->name, OBJ_KEY);
+ cdr = ao2_find(active_cdrs_by_channel, peer->uniqueid, OBJ_KEY);
}
if (!cdr) {
@@ -1986,6 +2023,7 @@
struct stasis_cache_update *update = stasis_message_data(message);
struct ast_channel_snapshot *old_snapshot;
struct ast_channel_snapshot *new_snapshot;
+ const char *uniqueid;
const char *name;
struct cdr_object *it_cdr;
@@ -1994,16 +2032,12 @@
old_snapshot = stasis_message_data(update->old_snapshot);
new_snapshot = stasis_message_data(update->new_snapshot);
+ uniqueid = new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid;
name = new_snapshot ? new_snapshot->name : old_snapshot->name;
if (filter_channel_cache_message(old_snapshot, new_snapshot)) {
return;
}
-
- CDR_DEBUG(mod_cfg, "Channel Update message for %s: %u.%08u\n",
- name,
- (unsigned int)stasis_message_timestamp(message)->tv_sec,
- (unsigned int)stasis_message_timestamp(message)->tv_usec);
if (new_snapshot && !old_snapshot) {
cdr = cdr_object_alloc(new_snapshot);
@@ -2015,7 +2049,7 @@
/* Handle Party A */
if (!cdr) {
- cdr = ao2_find(active_cdrs_by_channel, name, OBJ_KEY);
+ cdr = ao2_find(active_cdrs_by_channel, uniqueid, OBJ_KEY);
}
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", name);
@@ -2027,7 +2061,6 @@
if (!it_cdr->fn_table->process_party_a) {
continue;
}
- CDR_DEBUG(mod_cfg, "%p - Processing new channel snapshot %s\n", it_cdr, new_snapshot->name);
all_reject &= it_cdr->fn_table->process_party_a(it_cdr, new_snapshot);
}
if (all_reject && check_new_cdr_needed(old_snapshot, new_snapshot)) {
@@ -2121,7 +2154,7 @@
RAII_VAR(struct module_config *, mod_cfg,
ao2_global_obj_ref(module_configs), ao2_cleanup);
RAII_VAR(struct cdr_object *, cdr,
- ao2_find(active_cdrs_by_channel, channel->name, OBJ_KEY),
+ ao2_find(active_cdrs_by_channel, channel->uniqueid, OBJ_KEY),
ao2_cleanup);
struct cdr_object *it_cdr;
struct bridge_leave_data leave_data = {
@@ -2171,163 +2204,6 @@
}
}
-struct bridge_candidate {
- struct cdr_object *cdr; /*!< The actual CDR this candidate belongs to, either as A or B */
- struct cdr_object_snapshot candidate; /*!< The candidate for a new pairing */
-};
-
-/*! \internal
- * \brief Comparison function for \ref bridge_candidate objects
- */
-static int bridge_candidate_cmp_fn(void *obj, void *arg, int flags)
-{
- struct bridge_candidate *left = obj;
- struct bridge_candidate *right = arg;
- const char *match = (flags & OBJ_KEY) ? arg : right->candidate.snapshot->name;
- return strcasecmp(left->candidate.snapshot->name, match) ? 0 : (CMP_MATCH | CMP_STOP);
-}
-
-/*! \internal
- * \brief Hash function for \ref bridge_candidate objects
- */
-static int bridge_candidate_hash_fn(const void *obj, const int flags)
-{
- const struct bridge_candidate *bc = obj;
- const char *id = (flags & OBJ_KEY) ? obj : bc->candidate.snapshot->name;
- return ast_str_case_hash(id);
-}
-
-/*! \brief \ref bridge_candidate Destructor */
-static void bridge_candidate_dtor(void *obj)
-{
- struct bridge_candidate *bcand = obj;
- ao2_cleanup(bcand->cdr);
- ao2_cleanup(bcand->candidate.snapshot);
- free_variables(&bcand->candidate.variables);
-}
-
-/*!
- * \brief \ref bridge_candidate Constructor
- * \param cdr The \ref cdr_object that is a candidate for being compared to in
- * a bridge operation
- * \param candidate The \ref cdr_object_snapshot candidate snapshot in the CDR
- * that should be used during the operaton
- */
-static struct bridge_candidate *bridge_candidate_alloc(struct cdr_object *cdr, struct cdr_object_snapshot *candidate)
-{
- struct bridge_candidate *bcand;
-
- bcand = ao2_alloc(sizeof(*bcand), bridge_candidate_dtor);
- if (!bcand) {
- return NULL;
- }
- bcand->cdr = cdr;
- ao2_ref(bcand->cdr, +1);
- bcand->candidate.flags = candidate->flags;
- strcpy(bcand->candidate.userfield, candidate->userfield);
- bcand->candidate.snapshot = candidate->snapshot;
- ao2_ref(bcand->candidate.snapshot, +1);
- copy_variables(&bcand->candidate.variables, &candidate->variables);
-
- return bcand;
-}
-
-/*!
- * \internal
- * \brief Build and add bridge candidates based on a CDR
- *
- * \param bridge_id The ID of the bridge we need candidates for
- * \param candidates The container of \ref bridge_candidate objects
- * \param cdr The \ref cdr_object that is our candidate
- * \param party_a Non-zero if we should look at the Party A channel; 0 if Party B
- */
-static void add_candidate_for_bridge(const char *bridge_id,
- struct ao2_container *candidates,
- struct cdr_object *cdr,
- int party_a)
-{
- struct cdr_object *it_cdr;
-
- for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
- struct cdr_object_snapshot *party_snapshot;
- RAII_VAR(struct bridge_candidate *, bcand, NULL, ao2_cleanup);
-
- party_snapshot = party_a ? &it_cdr->party_a : &it_cdr->party_b;
-
- if (it_cdr->fn_table != &bridge_state_fn_table || strcmp(bridge_id, it_cdr->bridge)) {
- continue;
- }
-
- if (!party_snapshot->snapshot) {
- continue;
- }
-
- /* Don't add a party twice */
- bcand = ao2_find(candidates, party_snapshot->snapshot->name, OBJ_KEY);
- if (bcand) {
- continue;
- }
-
- bcand = bridge_candidate_alloc(it_cdr, party_snapshot);
- if (bcand) {
- ao2_link(candidates, bcand);
- }
- }
-}
-
-/*!
- * \brief Create new \ref bridge_candidate objects for each party currently
- * in a bridge
- * \param bridge The \param ast_bridge_snapshot for the bridge we're processing
- *
- * Note that we use two passes here instead of one so that we only create a
- * candidate for a party B if they are never a party A in the bridge. Otherwise,
- * we don't care about them.
- */
-static struct ao2_container *create_candidates_for_bridge(struct ast_bridge_snapshot *bridge)
-{
- struct ao2_container *candidates = ao2_container_alloc(61, bridge_candidate_hash_fn, bridge_candidate_cmp_fn);
- char *bridge_id = ast_strdupa(bridge->uniqueid);
- struct ao2_iterator *it_cdrs;
- struct cdr_object *cand_cdr_master;
-
- if (!candidates) {
- return NULL;
- }
-
- /* For each CDR that has a record in the bridge, get their Party A and
- * make them a candidate. Note that we do this in two passes as opposed to one so
- * that we give preference CDRs where the channel is Party A */
- it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
- cdr_object_bridge_cmp_fn, bridge_id);
- if (!it_cdrs) {
- /* No one in the bridge yet! */
- ao2_cleanup(candidates);
- return NULL;
- }
- for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
- SCOPED_AO2LOCK(lock, cand_cdr_master);
- add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 1);
- }
- ao2_iterator_destroy(it_cdrs);
- /* For each CDR that has a record in the bridge, get their Party B and
- * make them a candidate. */
- it_cdrs = ao2_callback(active_cdrs_by_channel, OBJ_MULTIPLE,
- cdr_object_bridge_cmp_fn, bridge_id);
- if (!it_cdrs) {
- /* Now it's just an error. */
- ao2_cleanup(candidates);
- return NULL;
- }
- for (; (cand_cdr_master = ao2_iterator_next(it_cdrs)); ao2_cleanup(cand_cdr_master)) {
- SCOPED_AO2LOCK(lock, cand_cdr_master);
- add_candidate_for_bridge(bridge->uniqueid, candidates, cand_cdr_master, 0);
- }
- ao2_iterator_destroy(it_cdrs);
-
- return candidates;
-}
-
/*!
* \internal
* \brief Create a new CDR, append it to an existing CDR, and update its snapshots
@@ -2335,9 +2211,10 @@
* \note The new CDR will be automatically transitioned to the bridge state
*/
static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
- const char *bridge_id,
struct cdr_object_snapshot *party_b)
{
+ RAII_VAR(struct module_config *, mod_cfg,
+ ao2_global_obj_ref(module_configs), ao2_cleanup);
struct cdr_object *new_cdr;
new_cdr = cdr_object_create_and_append(cdr);
@@ -2348,76 +2225,70 @@
cdr_object_check_party_a_answer(new_cdr);
ast_string_field_set(new_cdr, bridge, cdr->bridge);
cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
-}
-
-/*!
- * \brief Process a single \ref bridge_candidate. Note that this is called as
- * part of an \ref ao2_callback on an \ref ao2_container of \ref bridge_candidate
- * objects previously created by \ref create_candidates_for_bridge.
+ CDR_DEBUG(mod_cfg, "%p - Party A %s has new Party B %s\n",
+ new_cdr, new_cdr->party_a.snapshot->name,
+ party_b->snapshot->name);
+}
+
+/*!
+ * \brief Process a single \ref bridge_candidate
*
- * \param obj The \ref bridge_candidate being processed
- * \param arg The \ref cdr_object that is being compared against the candidates
+ * When a CDR enters a bridge, it needs to make pairings with everyone else
+ * that it is not currently paired with. This function determines, for the
+ * CDR for the channel that entered the bridge and the CDR for every other
+ * channel currently in the bridge, who is Party A and makes new CDRs.
*
- * The purpose of this function is to create the necessary CDR entries as a
- * result of \ref cdr_object having entered the same bridge as the CDR
- * represented by \ref bridge_candidate.
- */
-static int bridge_candidate_process(void *obj, void *arg, int flags)
-{
- struct bridge_candidate *bcand = obj;
- struct cdr_object *cdr = arg;
+ * \param cdr The \ref cdr_obj being processed
+ * \param cand_cdr The \ref cdr_object that is a candidate
+ *
+ */
+static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
+{
+ RAII_VAR(struct module_config *, mod_cfg,
+ ao2_global_obj_ref(module_configs), ao2_cleanup);
struct cdr_object_snapshot *party_a;
-
- /* If the candidate is us or someone we've taken on, pass on by */
- if (!strcasecmp(cdr->party_a.snapshot->name, bcand->candidate.snapshot->name)
- || (cdr->party_b.snapshot
[... 402 lines stripped ...]
More information about the asterisk-commits
mailing list