mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	Merged revisions 295711 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ................ r295711 | russell | 2010-11-19 18:50:00 -0600 (Fri, 19 Nov 2010) | 36 lines Merged revisions 295710 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.6.2 ........ r295710 | russell | 2010-11-19 18:45:51 -0600 (Fri, 19 Nov 2010) | 29 lines Fix cache of device state changes for multiple servers. This patch addresses a regression where device states across multiple servers were not being processing completely correctly. The code works to determine the overall state by looking at the last known state of a device on each server. However, there was a regression due to some invasive rewrites of how the cache works that led to the cache only storing the last device state change for a device, regardless of which server it was on. The code is set up to cache device state change events by ensuring that each event in the cache has a unique device name + entity ID (server ID). The code that was responsible for comparing raw information elements (which EID is) always returned a match due to a memcmp() with a length of 0. There isn't much code to fix the actual bug. This patch also introduces a new CLI command that was very useful for debugging this problem. The command allows you to dump the contents of the event cache. (closes issue #18284) Reported by: klaus3000 Patches: issue18284.rev1.txt uploaded by russell (license 2) Tested by: russell, klaus3000 (closes issue #18280) Reported by: klaus3000 Review: https://reviewboard.asterisk.org/r/1012/ ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@295712 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		| @@ -583,6 +583,17 @@ uint32_t ast_event_get_ie_str_hash(const struct ast_event *event, enum ast_event | |||||||
|  */ |  */ | ||||||
| const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type); | const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_ie_type ie_type); | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |  * \brief Get the length of the raw payload for a particular IE | ||||||
|  |  * | ||||||
|  |  * \param event The event to get the IE payload length from | ||||||
|  |  * \param ie_type the type of information element to get the length of | ||||||
|  |  * | ||||||
|  |  * \return If an IE of type ie_type is found, its payload length is returned. | ||||||
|  |  *         Otherwise, 0 is returned. | ||||||
|  |  */ | ||||||
|  | uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type); | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief Get the string representation of an information element type |  * \brief Get the string representation of an information element type | ||||||
|  * |  * | ||||||
| @@ -724,6 +735,15 @@ const char *ast_event_iterator_get_ie_str(struct ast_event_iterator *iterator); | |||||||
|  */ |  */ | ||||||
| void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator); | void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator); | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |  * \brief Get the length of the raw payload for the current IE for an iterator | ||||||
|  |  * | ||||||
|  |  * \param iterator The IE iterator | ||||||
|  |  * | ||||||
|  |  * \return The payload length of the current IE | ||||||
|  |  */ | ||||||
|  | uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) || defined(c_plusplus) | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										161
									
								
								main/event.c
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								main/event.c
									
									
									
									
									
								
							| @@ -38,6 +38,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | |||||||
| #include "asterisk/utils.h" | #include "asterisk/utils.h" | ||||||
| #include "asterisk/taskprocessor.h" | #include "asterisk/taskprocessor.h" | ||||||
| #include "asterisk/astobj2.h" | #include "asterisk/astobj2.h" | ||||||
|  | #include "asterisk/cli.h" | ||||||
|  |  | ||||||
| static struct ast_taskprocessor *event_dispatcher; | static struct ast_taskprocessor *event_dispatcher; | ||||||
|  |  | ||||||
| @@ -182,6 +183,13 @@ static struct { | |||||||
| 	}, | 	}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /*! | ||||||
|  |  * \brief Names of cached event types, for CLI tab completion | ||||||
|  |  * | ||||||
|  |  * \note These names must match what is in the event_names array. | ||||||
|  |  */ | ||||||
|  | static const char * const cached_event_types[] = { "MWI", "DeviceState", "DeviceStateChange", NULL }; | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
|  * \brief Event Names |  * \brief Event Names | ||||||
|  */ |  */ | ||||||
| @@ -194,6 +202,7 @@ static const char * const event_names[AST_EVENT_TOTAL] = { | |||||||
| 	[AST_EVENT_DEVICE_STATE_CHANGE] = "DeviceStateChange", | 	[AST_EVENT_DEVICE_STATE_CHANGE] = "DeviceStateChange", | ||||||
| 	[AST_EVENT_CEL]                 = "CEL", | 	[AST_EVENT_CEL]                 = "CEL", | ||||||
| 	[AST_EVENT_SECURITY]            = "Security", | 	[AST_EVENT_SECURITY]            = "Security", | ||||||
|  | 	[AST_EVENT_NETWORK_CHANGE]      = "NetworkChange", | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /*! | /*! | ||||||
| @@ -275,7 +284,7 @@ int ast_event_str_to_event_type(const char *str, enum ast_event_type *event_type | |||||||
| 	int i; | 	int i; | ||||||
|  |  | ||||||
| 	for (i = 0; i < ARRAY_LEN(event_names); i++) { | 	for (i = 0; i < ARRAY_LEN(event_names); i++) { | ||||||
| 		if (strcasecmp(event_names[i], str)) { | 		if (ast_strlen_zero(event_names[i]) || strcasecmp(event_names[i], str)) { | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -539,8 +548,9 @@ static int match_ie_val(const struct ast_event *event, | |||||||
| 	case AST_EVENT_IE_PLTYPE_RAW: | 	case AST_EVENT_IE_PLTYPE_RAW: | ||||||
| 	{ | 	{ | ||||||
| 		const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw; | 		const void *buf = event2 ? ast_event_get_ie_raw(event2, ie_val->ie_type) : ie_val->payload.raw; | ||||||
|  | 		uint16_t ie_payload_len = event2 ? ast_event_get_ie_raw_payload_len(event2, ie_val->ie_type) : ie_val->raw_datalen; | ||||||
|  |  | ||||||
| 		return (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_val->raw_datalen)) ? 1 : 0; | 		return (buf && !memcmp(buf, ast_event_get_ie_raw(event, ie_val->ie_type), ie_payload_len)) ? 1 : 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	case AST_EVENT_IE_PLTYPE_EXISTS: | 	case AST_EVENT_IE_PLTYPE_EXISTS: | ||||||
| @@ -986,6 +996,11 @@ void *ast_event_iterator_get_ie_raw(struct ast_event_iterator *iterator) | |||||||
| 	return iterator->ie->ie_payload; | 	return iterator->ie->ie_payload; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | uint16_t ast_event_iterator_get_ie_raw_payload_len(struct ast_event_iterator *iterator) | ||||||
|  | { | ||||||
|  | 	return ntohs(iterator->ie->ie_payload_len); | ||||||
|  | } | ||||||
|  |  | ||||||
| enum ast_event_type ast_event_get_type(const struct ast_event *event) | enum ast_event_type ast_event_get_type(const struct ast_event *event) | ||||||
| { | { | ||||||
| 	return ntohs(event->type); | 	return ntohs(event->type); | ||||||
| @@ -1041,6 +1056,20 @@ const void *ast_event_get_ie_raw(const struct ast_event *event, enum ast_event_i | |||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | uint16_t ast_event_get_ie_raw_payload_len(const struct ast_event *event, enum ast_event_ie_type ie_type) | ||||||
|  | { | ||||||
|  | 	struct ast_event_iterator iterator; | ||||||
|  | 	int res; | ||||||
|  |  | ||||||
|  | 	for (res = ast_event_iterator_init(&iterator, event); !res; res = ast_event_iterator_next(&iterator)) { | ||||||
|  | 		if (ast_event_iterator_get_ie_type(&iterator) == ie_type) { | ||||||
|  | 			return ast_event_iterator_get_ie_raw_payload_len(&iterator); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type, | int ast_event_append_ie_str(struct ast_event **event, enum ast_event_ie_type ie_type, | ||||||
| 	const char *str) | 	const char *str) | ||||||
| { | { | ||||||
| @@ -1529,6 +1558,132 @@ static int ast_event_cmp(void *obj, void *arg, int flags) | |||||||
| 	return res; | 	return res; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void dump_raw_ie(struct ast_event_iterator *i, struct ast_cli_args *a) | ||||||
|  | { | ||||||
|  | 	char eid_buf[32]; | ||||||
|  | 	enum ast_event_ie_type ie_type; | ||||||
|  | 	const char *ie_type_name; | ||||||
|  |  | ||||||
|  | 	ie_type = ast_event_iterator_get_ie_type(i); | ||||||
|  | 	ie_type_name = ast_event_get_ie_type_name(ie_type); | ||||||
|  |  | ||||||
|  | 	switch (ie_type) { | ||||||
|  | 	case AST_EVENT_IE_EID: | ||||||
|  | 		ast_eid_to_str(eid_buf, sizeof(eid_buf), ast_event_iterator_get_ie_raw(i)); | ||||||
|  | 		ast_cli(a->fd, "%.30s: %s\n", ie_type_name, eid_buf); | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		ast_cli(a->fd, "%s\n", ie_type_name); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int event_dump_cli(void *obj, void *arg, int flags) | ||||||
|  | { | ||||||
|  | 	const struct ast_event_ref *event_ref = obj; | ||||||
|  | 	const struct ast_event *event = event_ref->event; | ||||||
|  | 	struct ast_cli_args *a = arg; | ||||||
|  | 	struct ast_event_iterator i; | ||||||
|  |  | ||||||
|  | 	if (ast_event_iterator_init(&i, event)) { | ||||||
|  | 		ast_cli(a->fd, "Failed to initialize event iterator.  :-(\n"); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ast_cli(a->fd, "Event: %s\n", ast_event_get_type_name(event)); | ||||||
|  |  | ||||||
|  | 	do { | ||||||
|  | 		enum ast_event_ie_type ie_type; | ||||||
|  | 		enum ast_event_ie_pltype ie_pltype; | ||||||
|  | 		const char *ie_type_name; | ||||||
|  |  | ||||||
|  | 		ie_type = ast_event_iterator_get_ie_type(&i); | ||||||
|  | 		ie_type_name = ast_event_get_ie_type_name(ie_type); | ||||||
|  | 		ie_pltype = ast_event_get_ie_pltype(ie_type); | ||||||
|  |  | ||||||
|  | 		switch (ie_pltype) { | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_UNKNOWN: | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_EXISTS: | ||||||
|  | 			ast_cli(a->fd, "%s\n", ie_type_name); | ||||||
|  | 			break; | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_STR: | ||||||
|  | 			ast_cli(a->fd, "%.30s: %s\n", ie_type_name, | ||||||
|  | 					ast_event_iterator_get_ie_str(&i)); | ||||||
|  | 			break; | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_UINT: | ||||||
|  | 			ast_cli(a->fd, "%.30s: %u\n", ie_type_name, | ||||||
|  | 					ast_event_iterator_get_ie_uint(&i)); | ||||||
|  | 			break; | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_BITFLAGS: | ||||||
|  | 			ast_cli(a->fd, "%.30s: %u\n", ie_type_name, | ||||||
|  | 					ast_event_iterator_get_ie_bitflags(&i)); | ||||||
|  | 			break; | ||||||
|  | 		case AST_EVENT_IE_PLTYPE_RAW: | ||||||
|  | 			dump_raw_ie(&i, a); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} while (!ast_event_iterator_next(&i)); | ||||||
|  |  | ||||||
|  | 	ast_cli(a->fd, "\n"); | ||||||
|  |  | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static char *event_dump_cache(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) | ||||||
|  | { | ||||||
|  | 	enum ast_event_type event_type; | ||||||
|  | 	enum ast_event_ie_type *cache_args; | ||||||
|  | 	int i; | ||||||
|  |  | ||||||
|  | 	switch (cmd) { | ||||||
|  | 	case CLI_INIT: | ||||||
|  | 		e->command = "event dump cache"; | ||||||
|  | 		e->usage = | ||||||
|  | 			"Usage: event dump cache <event type>\n" | ||||||
|  | 			"       Dump all of the cached events for the given event type.\n" | ||||||
|  | 			"       This is primarily intended for debugging.\n"; | ||||||
|  | 		return NULL; | ||||||
|  | 	case CLI_GENERATE: | ||||||
|  | 		if (a->pos == 3) { | ||||||
|  | 			return ast_cli_complete(a->word, cached_event_types, a->n); | ||||||
|  | 		} | ||||||
|  | 		return NULL; | ||||||
|  | 	case CLI_HANDLER: | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (a->argc != e->args + 1) { | ||||||
|  | 		return CLI_SHOWUSAGE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (ast_event_str_to_event_type(a->argv[e->args], &event_type)) { | ||||||
|  | 		ast_cli(a->fd, "Invalid cached event type: '%s'\n", a->argv[e->args]); | ||||||
|  | 		return CLI_SHOWUSAGE; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (!ast_event_cache[event_type].container) { | ||||||
|  | 		ast_cli(a->fd, "Event type '%s' has no cache.\n", a->argv[e->args]); | ||||||
|  | 		return CLI_SUCCESS; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ast_cli(a->fd, "Event Type: %s\n", a->argv[e->args]); | ||||||
|  | 	ast_cli(a->fd, "Cache Unique Keys:\n"); | ||||||
|  | 	cache_args = ast_event_cache[event_type].cache_args; | ||||||
|  | 	for (i = 0; i < ARRAY_LEN(ast_event_cache[0].cache_args) && cache_args[i]; i++) { | ||||||
|  | 		ast_cli(a->fd, "--> %s\n", ast_event_get_ie_type_name(cache_args[i])); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ast_cli(a->fd, "\n--- Begin Cache Dump ---\n\n"); | ||||||
|  | 	ao2_callback(ast_event_cache[event_type].container, OBJ_NODATA, event_dump_cli, a); | ||||||
|  | 	ast_cli(a->fd, "--- End Cache Dump ---\n\n"); | ||||||
|  |  | ||||||
|  | 	return CLI_SUCCESS; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static struct ast_cli_entry event_cli[] = { | ||||||
|  | 	AST_CLI_DEFINE(event_dump_cache, "Dump the internal event cache (for debugging)"), | ||||||
|  | }; | ||||||
|  |  | ||||||
| int ast_event_init(void) | int ast_event_init(void) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| @@ -1553,5 +1708,7 @@ int ast_event_init(void) | |||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	ast_cli_register_multiple(event_cli, ARRAY_LEN(event_cli)); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user