[asterisk-commits] russell: branch russell/events r59185 - in
/team/russell/events: apps/ includ...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Fri Mar 23 00:49:31 MST 2007
Author: russell
Date: Fri Mar 23 02:49:31 2007
New Revision: 59185
URL: http://svn.digium.com/view/asterisk?view=rev&rev=59185
Log:
* Add the ability to request that an event be cached when it is generated based
on specified fields of the event.
* Add a way to check the cache for events that match specified fields.
* Update res_eventtest to test this new code.
* Update app_voicemail to request that MWI events get cached based
on the mailbox.
Modified:
team/russell/events/apps/app_voicemail.c
team/russell/events/include/asterisk/event.h
team/russell/events/include/asterisk/event_defs.h
team/russell/events/main/event.c
team/russell/events/res/res_eventtest.c
Modified: team/russell/events/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/apps/app_voicemail.c?view=diff&rev=59185&r1=59184&r2=59185
==============================================================================
--- team/russell/events/apps/app_voicemail.c (original)
+++ team/russell/events/apps/app_voicemail.c Fri Mar 23 02:49:31 2007
@@ -3948,7 +3948,9 @@
if (ast_event_append_ie_uint(&event, AST_EVENT_IE_OLDMSGS, old))
return;
- ast_event_queue(event);
+ ast_event_queue_and_cache(event,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+ AST_EVENT_END);
}
static int notify_new_message(struct ast_channel *chan, struct ast_vm_user *vmu, int msgnum, long duration, char *fmt, char *cidnum, char *cidname)
Modified: team/russell/events/include/asterisk/event.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/event.h?view=diff&rev=59185&r1=59184&r2=59185
==============================================================================
--- team/russell/events/include/asterisk/event.h (original)
+++ team/russell/events/include/asterisk/event.h Fri Mar 23 02:49:31 2007
@@ -35,6 +35,8 @@
struct ast_event *ast_event_new(enum ast_event_type);
+void ast_event_destroy(struct ast_event *);
+
int ast_event_queue(struct ast_event *);
int ast_event_queue_and_cache(struct ast_event *, ...);
Modified: team/russell/events/include/asterisk/event_defs.h
URL: http://svn.digium.com/view/asterisk/team/russell/events/include/asterisk/event_defs.h?view=diff&rev=59185&r1=59184&r2=59185
==============================================================================
--- team/russell/events/include/asterisk/event_defs.h (original)
+++ team/russell/events/include/asterisk/event_defs.h Fri Mar 23 02:49:31 2007
@@ -28,6 +28,8 @@
/*! \brief Event types
* \note These values can *never* change. */
enum ast_event_type {
+ /*! Used to terminate the arguments to caching functions */
+ AST_EVENT_END = -1,
/*! Reserved to provide the ability to subscribe to all events. A specific
event should never have a payload of 0. */
AST_EVENT_ALL = 0x00,
@@ -52,6 +54,11 @@
AST_EVENT_IE_MAILBOX,
};
+enum ast_event_ie_pltype {
+ AST_EVENT_IE_PLTYPE_UINT,
+ AST_EVENT_IE_PLTYPE_STR,
+};
+
struct ast_event_ie {
enum ast_event_ie_type ie_type:16;
/*! Total length of the IE payload */
Modified: team/russell/events/main/event.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/main/event.c?view=diff&rev=59185&r1=59184&r2=59185
==============================================================================
--- team/russell/events/main/event.c (original)
+++ team/russell/events/main/event.c Fri Mar 23 02:49:31 2007
@@ -171,7 +171,7 @@
/* Invalid type */
if (type >= AST_EVENT_TOTAL) {
- ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
+ ast_log(LOG_WARNING, "Someone tried to create an event of invalid "
"type '%d'!\n", type);
return NULL;
}
@@ -185,23 +185,188 @@
return event;
}
+void ast_event_destroy(struct ast_event *event)
+{
+ free(event);
+}
+
+static void ast_event_ref_destroy(struct ast_event_ref *event_ref)
+{
+ ast_event_destroy(event_ref->event);
+ free(event_ref);
+}
+
+static struct ast_event *ast_event_dup(const struct ast_event *event)
+{
+ struct ast_event *dup_event;
+
+ if (!(dup_event = ast_calloc(1, event->event_len)))
+ return NULL;
+
+ memcpy(dup_event, event, event->event_len);
+
+ return dup_event;
+}
+
struct ast_event *ast_event_get_cached(enum ast_event_type type, ...)
{
- /* XXX Get event from cache matching specified IE parameters */
-
- return NULL;
+ va_list ap;
+ enum ast_event_ie_type ie_type;
+ struct ast_event *dup_event = NULL;
+ struct ast_event_ref *event_ref;
+ struct cache_arg {
+ AST_LIST_ENTRY(cache_arg) entry;
+ enum ast_event_ie_type ie_type;
+ enum ast_event_ie_pltype pltype;
+ union {
+ uint32_t uint;
+ const char *str;
+ } payload;
+ } *cache_arg;
+ AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
+
+ va_start(ap, type);
+ for (ie_type = va_arg(ap, enum ast_event_type);
+ ie_type != AST_EVENT_END;
+ ie_type = va_arg(ap, enum ast_event_type))
+ {
+ cache_arg = alloca(sizeof(*cache_arg));
+ cache_arg->ie_type = ie_type;
+ cache_arg->pltype = va_arg(ap, enum ast_event_ie_pltype);
+ if (cache_arg->pltype == AST_EVENT_IE_PLTYPE_UINT)
+ cache_arg->payload.uint = va_arg(ap, uint32_t);
+ else if (cache_arg->pltype == AST_EVENT_IE_PLTYPE_STR)
+ cache_arg->payload.str = ast_strdupa(va_arg(ap, const char *));
+ AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
+ }
+ va_end(ap);
+
+ if (AST_LIST_EMPTY(&cache_args)) {
+ ast_log(LOG_ERROR, "Events can not be retrieved from the cache without "
+ "specifying at least one IE type!\n");
+ return NULL;
+ }
+
+ AST_RWLIST_RDLOCK(&ast_event_cache[type]);
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
+ AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
+ if ( ! ( (cache_arg->pltype == AST_EVENT_IE_PLTYPE_UINT &&
+ (cache_arg->payload.uint ==
+ ast_event_get_ie_uint(event_ref->event, cache_arg->ie_type))) ||
+
+ (cache_arg->pltype == AST_EVENT_IE_PLTYPE_STR &&
+ (!strcmp(cache_arg->payload.str,
+ ast_event_get_ie_str(event_ref->event, cache_arg->ie_type)))) ) )
+ {
+ break;
+ }
+ }
+ if (!cache_arg) {
+ /* All parameters were matched on this cache entry, so return it */
+ dup_event = ast_event_dup(event_ref->event);
+ break;
+ }
+ }
+ AST_RWLIST_TRAVERSE_SAFE_END
+ AST_RWLIST_UNLOCK(&ast_event_cache[type]);
+
+ return dup_event;
+}
+
+/*! \brief Duplicate an event and add it to the cache
+ * \note This assumes this index in to the cache is locked */
+static int ast_event_dup_and_cache(const struct ast_event *event)
+{
+ struct ast_event *dup_event;
+ struct ast_event_ref *event_ref;
+
+ if (!(dup_event = ast_event_dup(event)))
+ return -1;
+ if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
+ return -1;
+
+ event_ref->event = dup_event;
+
+ AST_LIST_INSERT_TAIL(&ast_event_cache[event->type], event_ref, entry);
+
+ return 0;
}
int ast_event_queue_and_cache(struct ast_event *event, ...)
{
- /* XXX Add/Replace event in cache */
-
- return ast_event_queue(event);
+ va_list ap;
+ enum ast_event_type ie_type;
+ struct ast_event_ref *event_ref;
+ int res;
+ struct cache_arg {
+ AST_LIST_ENTRY(cache_arg) entry;
+ enum ast_event_ie_type ie_type;
+ enum ast_event_ie_pltype pltype;
+ } *cache_arg;
+ AST_LIST_HEAD_NOLOCK_STATIC(cache_args, cache_arg);
+
+ /* Invalid type */
+ if (event->type >= AST_EVENT_TOTAL) {
+ ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
+ "type '%d'!\n", event->type);
+ return -1;
+ }
+
+ va_start(ap, event);
+ for (ie_type = va_arg(ap, enum ast_event_type);
+ ie_type != AST_EVENT_END;
+ ie_type = va_arg(ap, enum ast_event_type))
+ {
+ cache_arg = alloca(sizeof(*cache_arg));
+ cache_arg->ie_type = ie_type;
+ cache_arg->pltype = va_arg(ap, enum ast_event_ie_pltype);
+ AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
+ }
+ va_end(ap);
+
+ if (AST_LIST_EMPTY(&cache_args)) {
+ ast_log(LOG_ERROR, "Events can not be cached without specifying at "
+ "least one IE type!\n");
+ return ast_event_queue(event);
+ }
+
+ AST_RWLIST_WRLOCK(&ast_event_cache[event->type]);
+ AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[event->type], event_ref, entry) {
+ AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
+ if ( ! ( (cache_arg->pltype == AST_EVENT_IE_PLTYPE_UINT &&
+ (ast_event_get_ie_uint(event, cache_arg->ie_type) ==
+ ast_event_get_ie_uint(event_ref->event, cache_arg->ie_type))) ||
+
+ (cache_arg->pltype == AST_EVENT_IE_PLTYPE_STR &&
+ (!strcmp(ast_event_get_ie_str(event, cache_arg->ie_type),
+ ast_event_get_ie_str(event_ref->event, cache_arg->ie_type)))) ) )
+ {
+ break;
+ }
+ }
+ if (!cache_arg) {
+ /* All parameters were matched on this cache entry, so remove it */
+ AST_LIST_REMOVE_CURRENT(&ast_event_cache[event->type], entry);
+ ast_event_ref_destroy(event_ref);
+ }
+ }
+ AST_RWLIST_TRAVERSE_SAFE_END
+ res = ast_event_dup_and_cache(event);
+ AST_RWLIST_UNLOCK(&ast_event_cache[event->type]);
+
+ return (ast_event_queue(event) || res) ? -1 : 0;
}
int ast_event_queue(struct ast_event *event)
{
struct ast_event_ref *event_ref;
+
+ /* Invalid type */
+ if (event->type >= AST_EVENT_TOTAL) {
+ ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
+ "type '%d'!\n", event->type);
+ return -1;
+ }
if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
return -1;
@@ -239,8 +404,7 @@
sub->cb(event_ref->event);
AST_RWLIST_UNLOCK(&ast_event_subs[AST_EVENT_ALL]);
- free(event_ref->event);
- free(event_ref);
+ ast_event_ref_destroy(event_ref);
}
return NULL;
Modified: team/russell/events/res/res_eventtest.c
URL: http://svn.digium.com/view/asterisk/team/russell/events/res/res_eventtest.c?view=diff&rev=59185&r1=59184&r2=59185
==============================================================================
--- team/russell/events/res/res_eventtest.c (original)
+++ team/russell/events/res/res_eventtest.c Fri Mar 23 02:49:31 2007
@@ -100,13 +100,53 @@
if (ast_event_append_ie_uint(&event, AST_EVENT_IE_OLDMSGS, old))
return CLI_FAILURE;
- ast_event_queue(event);
+ ast_event_queue_and_cache(event,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
+ AST_EVENT_END);
+
+ return CLI_SUCCESS;
+}
+
+static char *event_get_cached(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct ast_event *event;
+ const char *mailbox = "1234";
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "event get cached";
+ e->usage =
+ "Usage: event get cached\n"
+ " Test getting an event from the cache.\n";
+ return NULL;
+
+ case CLI_GENERATE:
+ return NULL; /* no completion */
+ }
+ if (a->argc != e->args)
+ return CLI_SHOWUSAGE;
+
+ event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
+ AST_EVENT_END);
+
+ if (!event) {
+ ast_cli(a->fd, "No event retrieved!\n");
+ return CLI_FAILURE;
+ }
+
+ ast_cli(a->fd, "Got the event. New: %u Old: %u\n",
+ ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS),
+ ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS));
+
+ ast_event_destroy(event);
return CLI_SUCCESS;
}
static struct ast_cli_entry cli_commands[] = {
NEW_CLI(event_gen, "Generate a test event"),
+ NEW_CLI(event_get_cached, "Get an event from the cache"),
};
static int load_module(void)
More information about the asterisk-commits
mailing list