[asterisk-commits] russell: branch 1.6.2 r258672 - in /branches/1.6.2: ./ main/event.c
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Apr 22 16:58:11 CDT 2010
Author: russell
Date: Thu Apr 22 16:58:06 2010
New Revision: 258672
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=258672
Log:
Merged revisions 258632 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
For 1.6.2, only merge the bug fixes, not the unit test.
........
r258632 | russell | 2010-04-22 16:06:53 -0500 (Thu, 22 Apr 2010) | 22 lines
Add ast_event subscription unit test and fix some ast_event API bugs.
This patch introduces another test in test_event.c that exercises most of the
subscription related ast_event API calls. I made some minor additions to the
existing event allocation test to increase API coverage by the test code.
Finally, I made a list in a comment of API calls not yet touched by the test
module as a to-do list for future test development.
During the development of this test code, I discovered a number of bugs in
the event API.
1) subscriptions to AST_EVENT_ALL were not handled appropriately in a couple
of different places. The API allows a subscription to all event types,
but with IE parameters, just as if it was a subscription to a specific
event type. However, the parameters were being ignored. This affected
ast_event_check_subscriber() and event distribution to subscribers.
2) Some of the logic in ast_event_check_subscriber() for checking subscriptions
against query parameters was wrong.
Review: https://reviewboard.asterisk.org/r/617/
........
Modified:
branches/1.6.2/ (props changed)
branches/1.6.2/main/event.c
Propchange: branches/1.6.2/
------------------------------------------------------------------------------
Binary property 'trunk-merged' - no diff available.
Modified: branches/1.6.2/main/event.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/main/event.c?view=diff&rev=258672&r1=258671&r2=258672
==============================================================================
--- branches/1.6.2/main/event.c (original)
+++ branches/1.6.2/main/event.c Thu Apr 22 16:58:06 2010
@@ -319,14 +319,62 @@
ast_free(ie_val);
}
+/*!
+ * \internal
+ * \brief Check if an ie_val matches a subscription
+ *
+ * \param sub subscription to check against
+ * \param ie_val IE value to check
+ *
+ * \retval 0 not matched
+ * \retval non-zero matched
+ */
+static int match_ie_val_to_sub(const struct ast_event_sub *sub, const struct ast_event_ie_val *ie_val)
+{
+ const struct ast_event_ie_val *sub_ie_val;
+ int res = 1;
+
+ AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) {
+ if (sub_ie_val->ie_type == ie_val->ie_type) {
+ break;
+ }
+ }
+
+ if (!sub_ie_val) {
+ /* This subscriber doesn't care about this IE, so consider
+ * it matched. */
+ return 1;
+ }
+
+ switch (ie_val->ie_pltype) {
+ case AST_EVENT_IE_PLTYPE_UINT:
+ res = (ie_val->payload.uint != sub_ie_val->payload.uint);
+ break;
+ case AST_EVENT_IE_PLTYPE_STR:
+ res = strcmp(ie_val->payload.str, sub_ie_val->payload.str);
+ break;
+ case AST_EVENT_IE_PLTYPE_RAW:
+ res = memcmp(ie_val->payload.raw,
+ sub_ie_val->payload.raw, ie_val->raw_datalen);
+ break;
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+ }
+
+ return res;
+}
+
enum ast_event_subscriber_res ast_event_check_subscriber(enum ast_event_type type, ...)
{
va_list ap;
enum ast_event_ie_type ie_type;
enum ast_event_subscriber_res res = AST_EVENT_SUB_NONE;
- struct ast_event_ie_val *ie_val, *sub_ie_val;
+ struct ast_event_ie_val *ie_val;
struct ast_event_sub *sub;
AST_LIST_HEAD_NOLOCK_STATIC(ie_vals, ast_event_ie_val);
+ const enum ast_event_type event_types[] = { type, AST_EVENT_ALL };
+ int i;
if (type >= AST_EVENT_TOTAL) {
ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
@@ -357,47 +405,42 @@
}
va_end(ap);
- AST_RWDLLIST_RDLOCK(&ast_event_subs[type]);
- AST_RWDLLIST_TRAVERSE(&ast_event_subs[type], sub, entry) {
- AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
- AST_LIST_TRAVERSE(&sub->ie_vals, sub_ie_val, entry) {
- if (sub_ie_val->ie_type == ie_val->ie_type)
+ for (i = 0; i < ARRAY_LEN(event_types); i++) {
+ AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
+ AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
+ AST_LIST_TRAVERSE(&ie_vals, ie_val, entry) {
+ if (match_ie_val_to_sub(sub, ie_val)) {
break;
+ }
}
- if (!sub_ie_val) {
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
- break;
- continue;
+
+ if (!ie_val) {
+ /* Everything matched. */
+ break;
}
- /* The subscriber doesn't actually care what the value is */
- if (sub_ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_EXISTS)
- continue;
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT &&
- ie_val->payload.uint != sub_ie_val->payload.uint)
- break;
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR &&
- strcmp(ie_val->payload.str, sub_ie_val->payload.str))
- break;
- if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_RAW &&
- memcmp(ie_val->payload.raw, sub_ie_val->payload.raw, ie_val->raw_datalen))
- break;
- }
- if (!ie_val)
- break;
- }
- AST_RWDLLIST_UNLOCK(&ast_event_subs[type]);
-
- if (sub) /* All parameters were matched */
- return AST_EVENT_SUB_EXISTS;
-
- AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]);
- if (!AST_DLLIST_EMPTY(&ast_event_subs[AST_EVENT_ALL]))
- res = AST_EVENT_SUB_EXISTS;
- AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
-
- return res;
-}
-
+ }
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
+ if (sub) {
+ break;
+ }
+ }
+
+ return sub ? AST_EVENT_SUB_EXISTS : AST_EVENT_SUB_NONE;
+}
+
+/*!
+ * \internal
+ * \brief Check if an ie_val matches an event
+ *
+ * \param event event to check against
+ * \param ie_val IE value to check
+ * \param event2 optional event, if specified, the value to compare against will be pulled
+ * from this event instead of from the ie_val structure. In this case, only the IE
+ * type and payload type will be pulled from ie_val.
+ *
+ * \retval 0 not matched
+ * \retval non-zero matched
+ */
static int match_ie_val(const struct ast_event *event,
const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
{
@@ -1118,32 +1161,28 @@
{
struct ast_event_ref *event_ref = data;
struct ast_event_sub *sub;
- uint16_t host_event_type;
-
- host_event_type = ntohs(event_ref->event->type);
-
- /* Subscribers to this specific event first */
- AST_RWDLLIST_RDLOCK(&ast_event_subs[host_event_type]);
- AST_RWDLLIST_TRAVERSE(&ast_event_subs[host_event_type], sub, entry) {
- struct ast_event_ie_val *ie_val;
- AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
- if (!match_ie_val(event_ref->event, ie_val, NULL)) {
- break;
+ const enum ast_event_type event_types[] = {
+ ntohs(event_ref->event->type),
+ AST_EVENT_ALL
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_LEN(event_types); i++) {
+ AST_RWDLLIST_RDLOCK(&ast_event_subs[event_types[i]]);
+ AST_RWDLLIST_TRAVERSE(&ast_event_subs[event_types[i]], sub, entry) {
+ struct ast_event_ie_val *ie_val;
+ AST_LIST_TRAVERSE(&sub->ie_vals, ie_val, entry) {
+ if (!match_ie_val(event_ref->event, ie_val, NULL)) {
+ break;
+ }
}
- }
- if (ie_val) {
- continue;
- }
- sub->cb(event_ref->event, sub->userdata);
- }
- AST_RWDLLIST_UNLOCK(&ast_event_subs[host_event_type]);
-
- /* Now to subscribers to all event types */
- AST_RWDLLIST_RDLOCK(&ast_event_subs[AST_EVENT_ALL]);
- AST_RWDLLIST_TRAVERSE(&ast_event_subs[AST_EVENT_ALL], sub, entry) {
- sub->cb(event_ref->event, sub->userdata);
- }
- AST_RWDLLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
+ if (ie_val) {
+ continue;
+ }
+ sub->cb(event_ref->event, sub->userdata);
+ }
+ AST_RWDLLIST_UNLOCK(&ast_event_subs[event_types[i]]);
+ }
ao2_ref(event_ref, -1);
More information about the asterisk-commits
mailing list