[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