[asterisk-commits] russell: branch russell/event_performance_trunk r184327 - in /team/russell/ev...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Mar 25 15:52:25 CDT 2009
Author: russell
Date: Wed Mar 25 15:52:14 2009
New Revision: 184327
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=184327
Log:
Look at that, ZOMBIES! I mean, it compiles.
Modified:
team/russell/event_performance_trunk/apps/app_minivm.c
team/russell/event_performance_trunk/apps/app_voicemail.c
team/russell/event_performance_trunk/channels/chan_dahdi.c
team/russell/event_performance_trunk/channels/chan_iax2.c
team/russell/event_performance_trunk/channels/chan_mgcp.c
team/russell/event_performance_trunk/channels/chan_sip.c
team/russell/event_performance_trunk/channels/chan_unistim.c
team/russell/event_performance_trunk/include/asterisk/_private.h
team/russell/event_performance_trunk/include/asterisk/devicestate.h
team/russell/event_performance_trunk/include/asterisk/event.h
team/russell/event_performance_trunk/include/asterisk/strings.h
team/russell/event_performance_trunk/main/asterisk.c
team/russell/event_performance_trunk/main/devicestate.c
team/russell/event_performance_trunk/main/event.c
team/russell/event_performance_trunk/res/ais/evt.c
Modified: team/russell/event_performance_trunk/apps/app_minivm.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/apps/app_minivm.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/apps/app_minivm.c (original)
+++ team/russell/event_performance_trunk/apps/app_minivm.c Wed Mar 25 15:52:14 2009
@@ -1785,13 +1785,10 @@
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, (new+urgent),
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, old,
AST_EVENT_IE_END))) {
- return;
- }
-
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
+ return;
+ }
+
+ ast_event_queue_and_cache(event);
}
/*! \brief Send MWI using interal Asterisk event subsystem */
Modified: team/russell/event_performance_trunk/apps/app_voicemail.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/apps/app_voicemail.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/apps/app_voicemail.c (original)
+++ team/russell/event_performance_trunk/apps/app_voicemail.c Wed Mar 25 15:52:14 2009
@@ -6215,10 +6215,7 @@
return;
}
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
+ ast_event_queue_and_cache(event);
}
/*!
Modified: team/russell/event_performance_trunk/channels/chan_dahdi.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/channels/chan_dahdi.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/channels/chan_dahdi.c (original)
+++ team/russell/event_performance_trunk/channels/chan_dahdi.c Wed Mar 25 15:52:14 2009
@@ -2959,10 +2959,7 @@
return;
}
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
+ ast_event_queue_and_cache(event);
if (!ast_strlen_zero(mailbox) && !ast_strlen_zero(mwimonitornotify)) {
snprintf(s, sizeof(s), "%s %s %d", mwimonitornotify, mailbox, thereornot);
@@ -3016,7 +3013,6 @@
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
if (event) {
Modified: team/russell/event_performance_trunk/channels/chan_iax2.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/channels/chan_iax2.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/channels/chan_iax2.c (original)
+++ team/russell/event_performance_trunk/channels/chan_iax2.c Wed Mar 25 15:52:14 2009
@@ -7394,8 +7394,6 @@
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
if (event) {
new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
Modified: team/russell/event_performance_trunk/channels/chan_mgcp.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/channels/chan_mgcp.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/channels/chan_mgcp.c (original)
+++ team/russell/event_performance_trunk/channels/chan_mgcp.c Wed Mar 25 15:52:14 2009
@@ -472,7 +472,6 @@
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cntx,
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
if (event) {
Modified: team/russell/event_performance_trunk/channels/chan_sip.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/channels/chan_sip.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/channels/chan_sip.c (original)
+++ team/russell/event_performance_trunk/channels/chan_sip.c Wed Mar 25 15:52:14 2009
@@ -18059,10 +18059,7 @@
AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new),
AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old),
AST_EVENT_IE_END))) {
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
+ ast_event_queue_and_cache(event);
}
}
@@ -21038,8 +21035,6 @@
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox->mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, S_OR(mailbox->context, "default"),
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
- AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
if (!event)
continue;
Modified: team/russell/event_performance_trunk/channels/chan_unistim.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/channels/chan_unistim.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/channels/chan_unistim.c (original)
+++ team/russell/event_performance_trunk/channels/chan_unistim.c Wed Mar 25 15:52:14 2009
@@ -4391,7 +4391,6 @@
event = ast_event_get_cached(AST_EVENT_MWI,
AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
- AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
AST_EVENT_IE_END);
if (event) {
Modified: team/russell/event_performance_trunk/include/asterisk/_private.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/include/asterisk/_private.h?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/include/asterisk/_private.h (original)
+++ team/russell/event_performance_trunk/include/asterisk/_private.h Wed Mar 25 15:52:14 2009
@@ -29,7 +29,7 @@
void dnsmgr_start_refresh(void); /*!< Provided by dnsmgr.c */
int dnsmgr_reload(void); /*!< Provided by dnsmgr.c */
void threadstorage_init(void); /*!< Provided by threadstorage.c */
-void ast_event_init(void); /*!< Provided by event.c */
+int ast_event_init(void); /*!< Provided by event.c */
int ast_device_state_engine_init(void); /*!< Provided by devicestate.c */
int astobj2_init(void); /*!< Provided by astobj2.c */
int ast_file_init(void); /*!< Provided by file.c */
Modified: team/russell/event_performance_trunk/include/asterisk/devicestate.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/include/asterisk/devicestate.h?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/include/asterisk/devicestate.h (original)
+++ team/russell/event_performance_trunk/include/asterisk/devicestate.h Wed Mar 25 15:52:14 2009
@@ -36,6 +36,8 @@
#ifndef _ASTERISK_DEVICESTATE_H
#define _ASTERISK_DEVICESTATE_H
+
+#include "asterisk/channel.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
@@ -260,6 +262,21 @@
unsigned int ring:1;
};
+/*!
+ * \brief Enable distributed device state processing.
+ *
+ * \details
+ * By default, Asterisk assumes that device state change events will only be
+ * originating from one instance. If a module gets loaded and configured such
+ * that multiple instances of Asterisk will be sharing device state, this
+ * function should be called to enable distributed device state processing.
+ * It is off by default to save on unnecessary processing.
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int ast_enable_distributed_devstate(void);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Modified: team/russell/event_performance_trunk/include/asterisk/event.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/include/asterisk/event.h?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/include/asterisk/event.h (original)
+++ team/russell/event_performance_trunk/include/asterisk/event.h Wed Mar 25 15:52:14 2009
@@ -358,42 +358,18 @@
*
* \param event the event to be queued and cached
*
- * The rest of the arguments to this function specify information elements to
- * use for determining which events in the cache that this event should replace.
- * All events in the cache that match the specified criteria will be removed from
- * the cache and then this one will be added. The arguments are specified in
- * the form:
- *
- * \code
- * <enum ast_event_ie_type>, [enum ast_event_ie_pltype]
- * \endcode
- * and must end with AST_EVENT_IE_END.
- *
- * If the ie_type specified is *not* AST_EVENT_IE_END, then it must be followed
- * by a valid IE payload type. If the payload type given is EXISTS, then all
- * events that contain that information element will be removed from the cache.
- * Otherwise, all events in the cache that contain an information element with
- * the same value as the new event will be removed.
- *
- * \note If more than one IE parameter is specified, they *all* must match for
- * the event to be removed from the cache.
- *
- * Example usage:
- *
- * \code
- * ast_event_queue_and_cache(event,
- * AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR,
- * AST_EVENT_IE_END);
- * \endcode
- *
- * This example queues and caches an event. Any events in the cache that have
- * the same MAILBOX information element as this event will be removed.
- *
+ * \details
* The purpose of caching events is so that the core can retain the last known
* information for events that represent some sort of state. That way, when
* code needs to find out the current state, it can query the cache.
- */
-int ast_event_queue_and_cache(struct ast_event *event, ...);
+ *
+ * The event API already knows which events can be cached and how to cache them.
+ *
+ * \retval 0 success
+ * \retval non-zero failure. If failure is returned, the event must be destroyed
+ * by the caller of this function.
+ */
+int ast_event_queue_and_cache(struct ast_event *event);
/*!
* \brief Retrieve an event from the cache
@@ -511,6 +487,18 @@
const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type);
/*!
+ * \brief Get the hash for the string payload of an IE
+ *
+ * \param event The event to get the IE from
+ * \param ie_type the type of information element to retrieve the hash for
+ *
+ * \return This function returns the hash value as calculated by ast_str_hash()
+ * for the string payload. This is stored in the event to avoid
+ * unnecessary string comparisons.
+ */
+uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type);
+
+/*!
* \brief Get the value of an information element that has a raw payload
*
* \param event The event to get the IE from
Modified: team/russell/event_performance_trunk/include/asterisk/strings.h
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/include/asterisk/strings.h?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/include/asterisk/strings.h (original)
+++ team/russell/event_performance_trunk/include/asterisk/strings.h Wed Mar 25 15:52:14 2009
@@ -852,6 +852,29 @@
}
/*!
+ * \brief Compute a hash value on a string
+ *
+ * \param[in] str The string to add to the hash
+ * \param[in] hash The hash value to add to
+ *
+ * \details
+ * This version of the function is for when you need to compute a
+ * string hash of more than one string.
+ *
+ * This famous hash algorithm was written by Dan Bernstein and is
+ * commonly used.
+ *
+ * \sa http://www.cse.yorku.ca/~oz/hash.html
+ */
+static force_inline int ast_str_hash_add(const char *str, int hash)
+{
+ while (*str)
+ hash = hash * 33 ^ *str++;
+
+ return abs(hash);
+}
+
+/*!
* \brief Compute a hash value on a case-insensitive string
*
* Uses the same hash algorithm as ast_str_hash, but converts
Modified: team/russell/event_performance_trunk/main/asterisk.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/main/asterisk.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/main/asterisk.c (original)
+++ team/russell/event_performance_trunk/main/asterisk.c Wed Mar 25 15:52:14 2009
@@ -3509,7 +3509,10 @@
}
#endif
- ast_event_init();
+ if (ast_event_init()) {
+ printf("%s", term_quit());
+ exit(1);
+ }
ast_makesocket();
sigemptyset(&sigs);
Modified: team/russell/event_performance_trunk/main/devicestate.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/main/devicestate.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/main/devicestate.c (original)
+++ team/russell/event_performance_trunk/main/devicestate.c Wed Mar 25 15:52:14 2009
@@ -196,8 +196,10 @@
ast_cond_t cond;
ast_mutex_t lock;
AST_LIST_HEAD_NOLOCK(, devstate_change) devstate_change_q;
+ unsigned int enabled:1;
} devstate_collector = {
.thread = AST_PTHREADT_NULL,
+ .enabled = 0,
};
/* Forward declarations */
@@ -428,22 +430,26 @@
static void devstate_event(const char *device, enum ast_device_state state)
{
struct ast_event *event;
+ enum ast_event_type event_type;
+
+ if (devstate_collector.enabled) {
+ /* Distributed device state is enabled, so this state change is a change
+ * for a single server, not the real state. */
+ event_type = AST_EVENT_DEVICE_STATE_CHANGE;
+ } else {
+ event_type = AST_EVENT_DEVICE_STATE;
+ }
ast_debug(3, "device '%s' state '%d'\n", device, state);
- if (!(event = ast_event_new(AST_EVENT_DEVICE_STATE_CHANGE,
+ if (!(event = ast_event_new(event_type,
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
AST_EVENT_IE_END))) {
return;
}
- /* Cache this event, replacing an event in the cache with the same
- * device name if it exists. */
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_EID, AST_EVENT_IE_PLTYPE_RAW, sizeof(struct ast_eid),
- AST_EVENT_IE_END);
+ ast_event_queue_and_cache(event);
}
/*! Called by the state change thread to find out what the state is, and then
@@ -632,13 +638,12 @@
AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR, device,
AST_EVENT_IE_STATE, AST_EVENT_IE_PLTYPE_UINT, state,
AST_EVENT_IE_END);
-
- if (!event)
+
+ if (!event) {
return;
-
- ast_event_queue_and_cache(event,
- AST_EVENT_IE_DEVICE, AST_EVENT_IE_PLTYPE_STR,
- AST_EVENT_IE_END);
+ }
+
+ ast_event_queue_and_cache(event);
}
static void handle_devstate_change(struct devstate_change *sc)
@@ -719,21 +724,6 @@
/*! \brief Initialize the device state engine in separate thread */
int ast_device_state_engine_init(void)
{
- devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
- devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
-
- if (!devstate_collector.event_sub) {
- ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
- return -1;
- }
-
- ast_mutex_init(&devstate_collector.lock);
- ast_cond_init(&devstate_collector.cond, NULL);
- if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
- ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
- return -1;
- }
-
ast_cond_init(&change_pending, NULL);
if (ast_pthread_create_background(&change_thread, NULL, do_devstate_changes, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to start device state change thread.\n");
@@ -830,3 +820,28 @@
return AST_DEVICE_NOT_INUSE;
}
+int ast_enable_distributed_devstate(void)
+{
+ if (devstate_collector.enabled) {
+ return 0;
+ }
+
+ devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
+ devstate_change_collector_cb, NULL, AST_EVENT_IE_END);
+
+ if (!devstate_collector.event_sub) {
+ ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
+ return -1;
+ }
+
+ ast_mutex_init(&devstate_collector.lock);
+ ast_cond_init(&devstate_collector.cond, NULL);
+ if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
+ ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
+ return -1;
+ }
+
+ devstate_collector.enabled = 1;
+
+ return 0;
+}
Modified: team/russell/event_performance_trunk/main/event.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/main/event.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/main/event.c (original)
+++ team/russell/event_performance_trunk/main/event.c Wed Mar 25 15:52:14 2009
@@ -28,6 +28,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/_private.h"
+
#include "asterisk/event.h"
#include "asterisk/linkedlists.h"
#include "asterisk/dlinkedlists.h"
@@ -36,6 +37,7 @@
#include "asterisk/unaligned.h"
#include "asterisk/utils.h"
#include "asterisk/taskprocessor.h"
+#include "asterisk/astobj2.h"
struct ast_taskprocessor *event_dispatcher;
@@ -52,6 +54,16 @@
/*! Total length of the IE payload */
uint16_t ie_payload_len;
unsigned char ie_payload[0];
+} __attribute__((packed));
+
+/*!
+ * \brief The payload for a string information element
+ */
+struct ast_event_ie_str_payload {
+ /*! \brief A hash calculated with ast_str_hash(), to speed up comparisons */
+ uint32_t hash;
+ /*! \brief The actual string, null terminated */
+ char str[1];
} __attribute__((packed));
/*!
@@ -85,7 +97,10 @@
enum ast_event_ie_pltype ie_pltype;
union {
uint32_t uint;
- const char *str;
+ struct {
+ uint32_t hash;
+ const char *str;
+ };
void *raw;
} payload;
size_t raw_datalen;
@@ -107,11 +122,55 @@
* The event subscribers are indexed by which event they are subscribed to */
static AST_RWDLLIST_HEAD(ast_event_sub_list, ast_event_sub) ast_event_subs[AST_EVENT_TOTAL];
-/*! \brief Cached events
- * The event cache is indexed on the event type. The purpose of this is
- * for events that express some sort of state. So, when someone first
- * needs to know this state, it can get the last known state from the cache. */
-static AST_RWLIST_HEAD(ast_event_ref_list, ast_event_ref) ast_event_cache[AST_EVENT_TOTAL];
+static int ast_event_cmp(void *obj, void *arg, int flags);
+static int ast_event_hash_mwi(const void *obj, const int flags);
+static int ast_event_hash_devstate(const void *obj, const int flags);
+static int ast_event_hash_devstate_change(const void *obj, const int flags);
+
+#ifdef LOW_MEMORY
+#define NUM_CACHE_BUCKETS 17
+#else
+#define NUM_CACHE_BUCKETS 563
+#endif
+
+#define MAX_CACHE_ARGS 8
+
+/*!
+ * \brief Event types that are kept in the cache.
+ */
+static struct {
+ /*!
+ * \brief Container of cached events
+ *
+ * \details This gets allocated in ast_event_init() when Asterisk starts
+ * for the event types declared as using the cache.
+ */
+ struct ao2_container *container;
+ /*! \brief Event type specific hash function */
+ ao2_hash_fn *hash_fn;
+ /*!
+ * \brief Information Elements used for caching
+ *
+ * \details This array is the set of information elements that will be unique
+ * among all events in the cache for this event type. When a new event gets
+ * cached, a previous event with the same values for these information elements
+ * will be replaced.
+ */
+ enum ast_event_ie_type cache_args[MAX_CACHE_ARGS];
+} ast_event_cache[AST_EVENT_TOTAL] = {
+ [AST_EVENT_MWI] = {
+ .hash_fn = ast_event_hash_mwi,
+ .cache_args = { AST_EVENT_IE_MAILBOX, AST_EVENT_IE_CONTEXT },
+ },
+ [AST_EVENT_DEVICE_STATE] = {
+ .hash_fn = ast_event_hash_devstate,
+ .cache_args = { AST_EVENT_IE_DEVICE, },
+ },
+ [AST_EVENT_DEVICE_STATE_CHANGE] = {
+ .hash_fn = ast_event_hash_devstate_change,
+ .cache_args = { AST_EVENT_IE_DEVICE, AST_EVENT_IE_EID, },
+ },
+};
/*!
* The index of each entry _must_ match the event type number!
@@ -237,6 +296,8 @@
{
switch (ie_val->ie_pltype) {
case AST_EVENT_IE_PLTYPE_STR:
+ ast_free((char *) ie_val->payload.str);
+ break;
case AST_EVENT_IE_PLTYPE_RAW:
ast_free(ie_val->payload.raw);
break;
@@ -328,7 +389,8 @@
return res;
}
-static int match_ie_val(struct ast_event *event, struct ast_event_ie_val *ie_val, struct ast_event *event2)
+static int match_ie_val(const struct ast_event *event,
+ const struct ast_event_ie_val *ie_val, const struct ast_event *event2)
{
if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_UINT) {
uint32_t val = event2 ? ast_event_get_ie_uint(event2, ie_val->ie_type) : ie_val->payload.uint;
@@ -338,9 +400,19 @@
}
if (ie_val->ie_pltype == AST_EVENT_IE_PLTYPE_STR) {
- const char *str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
- if (str && !strcmp(str, ast_event_get_ie_str(event, ie_val->ie_type)))
+ const char *str;
+ uint32_t hash;
+
+ hash = event2 ? ast_event_get_ie_str_hash(event2, ie_val->ie_type) : ie_val->payload.hash;
+ if (hash != ast_event_get_ie_str_hash(event, ie_val->ie_type)) {
+ return 0;
+ }
+
+ str = event2 ? ast_event_get_ie_str(event2, ie_val->ie_type) : ie_val->payload.str;
+ if (str && !strcmp(str, ast_event_get_ie_str(event, ie_val->ie_type))) {
return 1;
+ }
+
return 0;
}
@@ -360,26 +432,32 @@
return 0;
}
+static int dump_cache_cb(void *obj, void *arg, int flags)
+{
+ const struct ast_event_ref *event_ref = obj;
+ const struct ast_event *event = event_ref->event;
+ const struct ast_event_sub *event_sub = arg;
+ struct ast_event_ie_val *ie_val = NULL;
+
+ AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
+ if (!match_ie_val(event, ie_val, NULL)) {
+ break;
+ }
+ }
+
+ if (!ie_val) {
+ /* All parameters were matched on this cache entry, so dump it */
+ event_sub->cb(event, event_sub->userdata);
+ }
+
+ return 0;
+}
+
/*! \brief Dump the event cache for the subscribed event type */
void ast_event_dump_cache(const struct ast_event_sub *event_sub)
{
- struct ast_event_ref *event_ref;
- enum ast_event_type type = event_sub->type;
-
- AST_RWLIST_RDLOCK(&ast_event_cache[type]);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[type], event_ref, entry) {
- struct ast_event_ie_val *ie_val;
- AST_LIST_TRAVERSE(&event_sub->ie_vals, ie_val, entry) {
- if (!match_ie_val(event_ref->event, ie_val, NULL))
- break;
- }
- if (!ie_val) {
- /* All parameters were matched on this cache entry, so dump it */
- event_sub->cb(event_ref->event, event_sub->userdata);
- }
- }
- AST_RWLIST_TRAVERSE_SAFE_END
- AST_RWLIST_UNLOCK(&ast_event_cache[type]);
+ ao2_callback(ast_event_cache[event_sub->type].container, OBJ_NODATA,
+ dump_cache_cb, (void *) event_sub);
}
static struct ast_event *gen_sub_event(struct ast_event_sub *sub)
@@ -535,6 +613,8 @@
ast_free(ie_val);
return -1;
}
+
+ ie_val->payload.hash = ast_str_hash(str);
AST_LIST_INSERT_TAIL(&sub->ie_vals, ie_val, entry);
@@ -703,7 +783,11 @@
const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator)
{
- return (const char*)iterator->ie->ie_payload;
+ const struct ast_event_ie_str_payload *str_payload;
+
+ str_payload = (struct ast_event_ie_str_payload *) iterator->ie->ie_payload;
+
+ return str_payload->str;
}
void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator)
@@ -725,9 +809,22 @@
return ie_val ? ntohl(get_unaligned_uint32(ie_val)) : 0;
}
+uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event_ie_type ie_type)
+{
+ const struct ast_event_ie_str_payload *str_payload;
+
+ str_payload = ast_event_get_ie_raw(event, ie_type);
+
+ return str_payload->hash;
+}
+
const char *ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
{
- return ast_event_get_ie_raw(event, ie_type);
+ const struct ast_event_ie_str_payload *str_payload;
+
+ str_payload = ast_event_get_ie_raw(event, ie_type);
+
+ return str_payload->str;
}
const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type)
@@ -746,7 +843,16 @@
int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type,
const char *str)
{
- return ast_event_append_ie_raw(event, ie_type, str, strlen(str) + 1);
+ struct ast_event_ie_str_payload *str_payload;
+ size_t payload_len;
+
+ payload_len = sizeof(*str_payload) + strlen(str);
+ str_payload = alloca(payload_len);
+
+ strcpy(str_payload->str, str);
+ str_payload->hash = ast_str_hash(str);
+
+ return ast_event_append_ie_raw(event, ie_type, str_payload, payload_len);
}
int ast_event_append_ie_uint(struct ast_event **event, enum ast_event_ie_type ie_type,
@@ -850,10 +956,11 @@
ast_free(event);
}
-static void ast_event_ref_destroy(struct ast_event_ref *event_ref)
-{
+static void ast_event_ref_destroy(void *obj)
+{
+ struct ast_event_ref *event_ref = obj;
+
ast_event_destroy(event_ref->event);
- ast_free(event_ref);
}
static struct ast_event *ast_event_dup(const struct ast_event *event)
@@ -863,9 +970,10 @@
event_len = ast_event_get_size(event);
- if (!(dup_event = ast_calloc(1, event_len)))
+ if (!(dup_event = ast_calloc(1, event_len))) {
return NULL;
-
+ }
+
memcpy(dup_event, event, event_len);
return dup_event;
@@ -876,12 +984,24 @@
va_list ap;
enum ast_event_ie_type ie_type;
struct ast_event *dup_event = NULL;
- struct ast_event_ref *event_ref;
- struct ast_event_ie_val *cache_arg;
- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
+ struct ast_event_ref *cached_event_ref;
+ struct ast_event *cache_arg_event;
+ struct ast_event_ref tmp_event_ref = {
+ .event = NULL,
+ };
+ struct ao2_container *container = NULL;
if (type >= AST_EVENT_TOTAL) {
ast_log(LOG_ERROR, "%u is an invalid type!\n", type);
+ return NULL;
+ }
+
+ if (!(container = ast_event_cache[type].container)) {
+ ast_log(LOG_ERROR, "%u is not a cached event type\n", type);
+ return NULL;
+ }
+
+ if (!(cache_arg_event = ast_event_new(type, AST_EVENT_IE_END))) {
return NULL;
}
@@ -890,125 +1010,96 @@
ie_type != AST_EVENT_IE_END;
ie_type = va_arg(ap, enum ast_event_type))
{
- cache_arg = alloca(sizeof(*cache_arg));
- memset(cache_arg, 0, sizeof(*cache_arg));
- cache_arg->ie_type = ie_type;
- cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
- if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_UINT)
- cache_arg->payload.uint = va_arg(ap, uint32_t);
- else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_STR)
- cache_arg->payload.str = ast_strdupa(va_arg(ap, const char *));
- else if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW) {
+ enum ast_event_ie_pltype ie_pltype;
+
+ ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
+
+ switch (ie_pltype) {
+ case AST_EVENT_IE_PLTYPE_UINT:
+ ast_event_append_ie_uint(&cache_arg_event, ie_type, va_arg(ap, uint32_t));
+ break;
+ case AST_EVENT_IE_PLTYPE_STR:
+ ast_event_append_ie_str(&cache_arg_event, ie_type, va_arg(ap, const char *));
+ break;
+ case AST_EVENT_IE_PLTYPE_RAW:
+ {
void *data = va_arg(ap, void *);
size_t datalen = va_arg(ap, size_t);
- cache_arg->payload.raw = alloca(datalen);
- memcpy(cache_arg->payload.raw, data, datalen);
- cache_arg->raw_datalen = datalen;
- }
- AST_LIST_INSERT_TAIL(&cache_args, cache_arg, entry);
+ ast_event_append_ie_raw(&cache_arg_event, ie_type, data, datalen);
+ }
+ case AST_EVENT_IE_PLTYPE_EXISTS:
+ ast_log(LOG_WARNING, "PLTYPE_EXISTS not supported by this function\n");
+ break;
+ case AST_EVENT_IE_PLTYPE_UNKNOWN:
+ break;
+ }
}
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 (!match_ie_val(event_ref->event, cache_arg, NULL))
- 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]);
+ tmp_event_ref.event = cache_arg_event;
+
+ cached_event_ref = ao2_find(container, &tmp_event_ref, OBJ_POINTER);
+
+ ast_event_destroy(cache_arg_event);
+ cache_arg_event = NULL;
+
+ if (cached_event_ref) {
+ dup_event = ast_event_dup(cached_event_ref->event);
+ ao2_ref(cached_event_ref, -1);
+ cached_event_ref = NULL;
+ }
return dup_event;
+}
+
+static struct ast_event_ref *alloc_event_ref(void)
+{
+ return ao2_alloc(sizeof(struct ast_event_ref), ast_event_ref_destroy);
}
/*! \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)
+static int attribute_unused 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;
-
+ if (!(dup_event = ast_event_dup(event))) {
+ return -1;
+ }
+
+ if (!(event_ref = alloc_event_ref())) {
+ ast_event_destroy(dup_event);
+ return -1;
+ }
+
event_ref->event = dup_event;
- AST_LIST_INSERT_TAIL(&ast_event_cache[ntohs(event->type)], event_ref, entry);
+ ao2_link(ast_event_cache[ast_event_get_type(event)].container, event_ref);
+
+ ao2_ref(event_ref, -1);
return 0;
}
-int ast_event_queue_and_cache(struct ast_event *event, ...)
-{
- va_list ap;
- enum ast_event_type ie_type;
- uint16_t host_event_type;
- struct ast_event_ref *event_ref;
- int res;
- struct ast_event_ie_val *cache_arg;
- AST_LIST_HEAD_NOLOCK_STATIC(cache_args, ast_event_ie_val);
-
- host_event_type = ntohs(event->type);
-
- /* Invalid type */
- if (host_event_type >= AST_EVENT_TOTAL) {
- ast_log(LOG_WARNING, "Someone tried to queue an event of invalid "
- "type '%d'!\n", host_event_type);
- return -1;
- }
-
- va_start(ap, event);
- for (ie_type = va_arg(ap, enum ast_event_type);
- ie_type != AST_EVENT_IE_END;
- ie_type = va_arg(ap, enum ast_event_type))
- {
- cache_arg = alloca(sizeof(*cache_arg));
- memset(cache_arg, 0, sizeof(*cache_arg));
- cache_arg->ie_type = ie_type;
- cache_arg->ie_pltype = va_arg(ap, enum ast_event_ie_pltype);
- if (cache_arg->ie_pltype == AST_EVENT_IE_PLTYPE_RAW)
- cache_arg->raw_datalen = va_arg(ap, size_t);
- 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[host_event_type]);
- AST_RWLIST_TRAVERSE_SAFE_BEGIN(&ast_event_cache[host_event_type], event_ref, entry) {
- AST_LIST_TRAVERSE(&cache_args, cache_arg, entry) {
- if (!match_ie_val(event_ref->event, cache_arg, event))
- break;
- }
- if (!cache_arg) {
- /* All parameters were matched on this cache entry, so remove it */
- AST_LIST_REMOVE_CURRENT(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[host_event_type]);
-
- return (ast_event_queue(event) || res) ? -1 : 0;
+int ast_event_queue_and_cache(struct ast_event *event)
+{
+ struct ao2_container *container;
+ struct ast_event_ref tmp_event_ref = {
+ .event = event,
+ };
+
+ if (!(container = ast_event_cache[ast_event_get_type(event)].container)) {
+ ast_log(LOG_WARNING, "cache requested for non-cached event type\n");
+ goto queue_event;
+ }
+
+ /* Remove matches from the cache */
+ ao2_callback(container, OBJ_POINTER | OBJ_UNLINK | OBJ_MULTIPLE | OBJ_NODATA,
+ ast_event_cmp, &tmp_event_ref);
+
+queue_event:
+ return ast_event_queue(event);
}
static int handle_event(void *data)
@@ -1024,22 +1115,25 @@
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))
+ if (!match_ie_val(event_ref->event, ie_val, NULL)) {
break;
- }
- if (ie_val)
+ }
+ }
+ 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)
+ 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]);
- ast_event_ref_destroy(event_ref);
+ ao2_ref(event_ref, -1);
return 0;
}
@@ -1059,29 +1153,149 @@
}
/* If nobody has subscribed to this event type, throw it away now */
- if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
- == AST_EVENT_SUB_NONE) {
+ if (ast_event_check_subscriber(host_event_type, AST_EVENT_IE_END)
+ == AST_EVENT_SUB_NONE) {
ast_event_destroy(event);
return 0;
}
- if (!(event_ref = ast_calloc(1, sizeof(*event_ref))))
- return -1;
+ if (!(event_ref = alloc_event_ref())) {
+ return -1;
+ }
event_ref->event = event;
return ast_taskprocessor_push(event_dispatcher, handle_event, event_ref);
}
-void ast_event_init(void)
-{
+static int ast_event_hash_mwi(const void *obj, const int flags)
+{
+ const struct ast_event *event = obj;
+ const char *mailbox = ast_event_get_ie_str(event, AST_EVENT_IE_MAILBOX);
+ const char *context = ast_event_get_ie_str(event, AST_EVENT_IE_CONTEXT);
+
+ return ast_str_hash_add(context, ast_str_hash(mailbox));
+}
+
+/*!
+ * \internal
+ * \brief Hash function for AST_EVENT_DEVICE_STATE
+ *
+ * \param[in] obj an ast_event
+ * \param[in] flags unused
+ *
+ * \return hash value
+ */
+static int ast_event_hash_devstate(const void *obj, const int flags)
+{
+ const struct ast_event *event = obj;
+
+ return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
+}
+
+/*!
+ * \internal
+ * \brief Hash function for AST_EVENT_DEVICE_STATE_CHANGE
+ *
+ * \param[in] obj an ast_event
+ * \param[in] flags unused
+ *
+ * \return hash value
+ */
+static int ast_event_hash_devstate_change(const void *obj, const int flags)
+{
+ const struct ast_event *event = obj;
+
+ return ast_str_hash(ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE));
+}
+
+static int ast_event_hash(const void *obj, const int flags)
+{
+ const struct ast_event_ref *event_ref;
+ const struct ast_event *event;
+ ao2_hash_fn *hash_fn;
+
+ event_ref = obj;
+ event = event_ref->event;
+
+ if (!(hash_fn = ast_event_cache[ast_event_get_type(event)].hash_fn)) {
+ return 0;
+ }
+
+ return hash_fn(event, flags);
+}
+
+/*!
+ * \internal
+ * \brief Compare two events
+ *
+ * \param[in] obj the first event, as an ast_event_ref
+ * \param[in] arg the second event, as an ast_event_ref
+ * \param[in] flags unused
+ *
+ * \pre Both events must be the same type.
+ * \pre The event type must be declared as a cached event type in ast_event_cache
+ *
+ * \details This function takes two events, and determines if they are considered
+ * equivalent. The values of information elements specified in the cache arguments
+ * for the event type are used to determine if the events are equivalent.
+ *
+ * \retval 0 No match
+ * \retval CMP_MATCH The events are considered equivalent based on the cache arguments
+ */
+static int ast_event_cmp(void *obj, void *arg, int flags)
+{
+ struct ast_event_ref *event_ref, *event_ref2;
+ struct ast_event *event, *event2;
+ int res = CMP_MATCH;
int i;
-
- for (i = 0; i < AST_EVENT_TOTAL; i++)
+ enum ast_event_ie_type *cache_args;
+
+ event_ref = obj;
+ event = event_ref->event;
+
+ event_ref2 = arg;
+ event2 = event_ref2->event;
+
+ cache_args = ast_event_cache[ast_event_get_type(event)].cache_args;
+
+ for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) {
+ struct ast_event_ie_val ie_val = {
+ .ie_type = cache_args[i],
+ };
+
+ if (!match_ie_val(event, &ie_val, event2)) {
+ res = 0;
+ break;
+ }
+ }
+
+ return res;
+}
+
+int ast_event_init(void)
+{
+ int i;
+
+ for (i = 0; i < AST_EVENT_TOTAL; i++) {
AST_RWDLLIST_HEAD_INIT(&ast_event_subs[i]);
-
- for (i = 0; i < AST_EVENT_TOTAL; i++)
- AST_RWLIST_HEAD_INIT(&ast_event_cache[i]);
-
- event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0);
-}
+ }
+
+ for (i = 0; i < AST_EVENT_TOTAL; i++) {
+ if (!ast_event_cache[i].hash_fn) {
+ /* This event type is not cached. */
+ continue;
+ }
+
+ if (!(ast_event_cache[i].container = ao2_container_alloc(NUM_CACHE_BUCKETS,
+ ast_event_hash, ast_event_cmp))) {
+ return -1;
+ }
+ }
+
+ if (!(event_dispatcher = ast_taskprocessor_get("core_event_dispatcher", 0))) {
+ return -1;
+ }
+
+ return 0;
+}
Modified: team/russell/event_performance_trunk/res/ais/evt.c
URL: http://svn.digium.com/svn-view/asterisk/team/russell/event_performance_trunk/res/ais/evt.c?view=diff&rev=184327&r1=184326&r2=184327
==============================================================================
--- team/russell/event_performance_trunk/res/ais/evt.c (original)
[... 82 lines stripped ...]
More information about the asterisk-commits
mailing list