[asterisk-commits] tilghman: trunk r103754 - in /trunk: ./ build_tools/ funcs/ include/asterisk/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Feb 17 22:43:34 CST 2008


Author: tilghman
Date: Sun Feb 17 22:43:33 2008
New Revision: 103754

URL: http://svn.digium.com/view/asterisk?view=rev&rev=103754
Log:
Context tracing for channels
(closes issue #11268)
 Reported by: moy
 Patches: 
       chantrace-datastored-encapsulated-rev94934.patch uploaded by moy (license 222)

Modified:
    trunk/CHANGES
    trunk/build_tools/cflags.xml
    trunk/funcs/func_channel.c
    trunk/include/asterisk/channel.h
    trunk/main/channel.c
    trunk/main/cli.c
    trunk/main/pbx.c

Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Sun Feb 17 22:43:33 2008
@@ -513,3 +513,6 @@
      do not come from the remote party.
   * Added the 'n' option to the SpeechBackground application to tell it to not
      answer the channel if it has not already been answered.
+  * Added a compiler flag, CHANNEL_TRACE, which permits channel tracing to be
+     turned on, via the CHANNEL(trace) dialplan function.  Could be useful for
+     dialplan debugging.

Modified: trunk/build_tools/cflags.xml
URL: http://svn.digium.com/view/asterisk/trunk/build_tools/cflags.xml?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/build_tools/cflags.xml (original)
+++ trunk/build_tools/cflags.xml Sun Feb 17 22:43:33 2008
@@ -59,4 +59,6 @@
 		<member name="BUSYDETECT_DEBUG" displayname="Enable additional busy detection debugging">
 			<defaultenabled>no</defaultenabled>
 		</member>
+		<member name="CHANNEL_TRACE" displayname="Enable CHANNEL(trace) function">
+		</member>
 	</category>

Modified: trunk/funcs/func_channel.c
URL: http://svn.digium.com/view/asterisk/trunk/funcs/func_channel.c?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/funcs/func_channel.c (original)
+++ trunk/funcs/func_channel.c Sun Feb 17 22:43:33 2008
@@ -71,6 +71,13 @@
 		ast_copy_string(buf, ast_getformatname(chan->readformat), len);
 	else if (!strcasecmp(data, "audiowriteformat"))
 		ast_copy_string(buf, ast_getformatname(chan->writeformat), len);
+#ifdef CHANNEL_TRACE
+	else if (!strcasecmp(data, "trace")) {
+		ast_channel_lock(chan);
+		ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len);
+		ast_channel_unlock(chan);
+	}
+#endif
 	else if (!strcasecmp(data, "tonezone") && chan->zone)
 		locked_copy_string(chan, buf, chan->zone->country, len);
 	else if (!strcasecmp(data, "language"))
@@ -105,6 +112,20 @@
 		locked_string_field_set(chan, language, value);
 	else if (!strcasecmp(data, "musicclass"))
 		locked_string_field_set(chan, musicclass, value);
+#ifdef CHANNEL_TRACE
+	else if (!strcasecmp(data, "trace")) {
+		ast_channel_lock(chan);
+		if (ast_true(value)) 
+			ret = ast_channel_trace_enable(chan);
+		else if (ast_false(value)) 
+			ret = ast_channel_trace_disable(chan);
+		else {
+			ret = -1;
+			ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).");
+		}
+		ast_channel_unlock(chan);
+	}
+#endif
 	else if (!strcasecmp(data, "tonezone")) {
 		struct ind_tone_zone *new_zone;
 		if (!(new_zone = ast_get_indication_zone(value))) {
@@ -156,6 +177,9 @@
 		"R/W	tonezone           zone for indications played\n"
 		"R/W	txgain             set txgain level on channel drivers that support it\n"
 		"R/O	videonativeformat  format used natively for video\n"
+#ifdef CHANNEL_TRACE
+		"R/W	trace              whether or not context tracing is enabled\n"
+#endif
 		"\n"
 		"chan_sip provides the following additional options:\n"
 		"R/O    rtpqos             Get QOS information about the RTP stream\n"

Modified: trunk/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/trunk/include/asterisk/channel.h?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/include/asterisk/channel.h (original)
+++ trunk/include/asterisk/channel.h Sun Feb 17 22:43:33 2008
@@ -826,6 +826,34 @@
  */
 const struct ast_channel_tech *ast_get_channel_tech(const char *name);
 
+#ifdef CHANNEL_TRACE
+/*! \brief Update the context backtrace if tracing is enabled
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_channel_trace_update(struct ast_channel *chan);
+
+/*! \brief Enable context tracing in the channel
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_channel_trace_enable(struct ast_channel *chan);
+
+/*! \brief Disable context tracing in the channel.
+ * \note Does not remove current trace entries
+ * \return Returns 0 on success, -1 on failure
+ */
+int ast_channel_trace_disable(struct ast_channel *chan);
+
+/*! \brief Whether or not context tracing is enabled
+ * \return Returns -1 when the trace is enabled. 0 if not.
+ */
+int ast_channel_trace_is_enabled(struct ast_channel *chan);
+
+/*! \brief Put the channel backtrace in a string
+ * \return Returns the amount of lines in the backtrace. -1 on error.
+ */
+int ast_channel_trace_serialize(struct ast_channel *chan, struct ast_str **out);
+#endif
+
 /*! \brief Hang up a channel  
  * \note This function performs a hard hangup on a channel.  Unlike the soft-hangup, this function
  * performs all stream stopping, etc, on the channel that needs to end.

Modified: trunk/main/channel.c
URL: http://svn.digium.com/view/asterisk/trunk/main/channel.c?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/main/channel.c (original)
+++ trunk/main/channel.c Sun Feb 17 22:43:33 2008
@@ -103,6 +103,22 @@
 	const struct ast_channel_tech *tech;
 	AST_LIST_ENTRY(chanlist) list;
 };
+
+#ifdef CHANNEL_TRACE
+/*! \brief Structure to hold channel context backtrace data */
+struct ast_chan_trace_data {
+	int enabled;
+	AST_LIST_HEAD_NOLOCK(, ast_chan_trace) trace;
+};
+
+/*! \brief Structure to save contexts where an ast_chan has been into */
+struct ast_chan_trace {
+	char context[AST_MAX_CONTEXT];
+	char exten[AST_MAX_EXTENSION];
+	int priority;
+	AST_LIST_ENTRY(ast_chan_trace) entry;
+};
+#endif
 
 /*! \brief the list of registered channel types */
 static AST_LIST_HEAD_NOLOCK_STATIC(backends, chanlist);
@@ -313,6 +329,133 @@
 	AST_CLI_DEFINE(handle_cli_core_show_channeltypes, "List available channel types"),
 	AST_CLI_DEFINE(handle_cli_core_show_channeltype,  "Give more details on that channel type")
 };
+
+#ifdef CHANNEL_TRACE
+/*! \brief Destructor for the channel trace datastore */
+static void ast_chan_trace_destroy_cb(void *data)
+{
+	struct ast_chan_trace *trace;
+	struct ast_chan_trace_data *traced = data;
+	while ((trace = AST_LIST_REMOVE_HEAD(&traced->trace, entry))) {
+		ast_free(trace);
+	}
+	ast_free(traced);
+}
+
+/*! \brief Datastore to put the linked list of ast_chan_trace and trace status */
+const struct ast_datastore_info ast_chan_trace_datastore_info = {
+	.type = "ChanTrace",
+	.destroy = ast_chan_trace_destroy_cb
+};
+
+/*! \brief Put the channel backtrace in a string */
+int ast_channel_trace_serialize(struct ast_channel *chan, struct ast_str **buf)
+{
+	int total = 0;
+	struct ast_chan_trace *trace;
+	struct ast_chan_trace_data *traced;
+	struct ast_datastore *store;
+
+	ast_channel_lock(chan);
+	store = ast_channel_datastore_find(chan, &ast_chan_trace_datastore_info, NULL);
+	if (!store) {
+		ast_channel_unlock(chan);
+		return total;
+	}
+	traced = store->data;
+	(*buf)->used = 0;
+	(*buf)->str[0] = '\0';
+	AST_LIST_TRAVERSE(&traced->trace, trace, entry) {
+		if (ast_str_append(buf, 0, "[%d] => %s, %s, %d\n", total, trace->context, trace->exten, trace->priority) < 0) {
+			ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
+			total = -1;
+			break;
+		}
+		total++;
+	}
+	ast_channel_unlock(chan);
+	return total;
+}
+
+/* !\brief Whether or not context tracing is enabled */
+int ast_channel_trace_is_enabled(struct ast_channel *chan)
+{
+	struct ast_datastore *store = ast_channel_datastore_find(chan, &ast_chan_trace_datastore_info, NULL);
+	if (!store)
+		return 0;
+	return ((struct ast_chan_trace_data *)store->data)->enabled;
+}
+
+/*! \brief Update the context backtrace data if tracing is enabled */
+static int ast_channel_trace_data_update(struct ast_channel *chan, struct ast_chan_trace_data *traced)
+{
+	struct ast_chan_trace *trace;
+	if (!traced->enabled)
+		return 0;
+	/* If the last saved context does not match the current one
+	   OR we have not saved any context so far, then save the current context */
+	if ((!AST_LIST_EMPTY(&traced->trace) && strcasecmp(AST_LIST_FIRST(&traced->trace)->context, chan->context)) || 
+	    (AST_LIST_EMPTY(&traced->trace))) {
+		/* Just do some debug logging */
+		if (AST_LIST_EMPTY(&traced->trace))
+			ast_log(LOG_DEBUG, "Setting initial trace context to %s\n", chan->context);
+		else
+			ast_log(LOG_DEBUG, "Changing trace context from %s to %s\n", AST_LIST_FIRST(&traced->trace)->context, chan->context);
+		/* alloc or bail out */
+		trace = ast_malloc(sizeof(*trace));
+		if (!trace) 
+			return -1;
+		/* save the current location and store it in the trace list */
+		ast_copy_string(trace->context, chan->context, sizeof(trace->context));
+		ast_copy_string(trace->exten, chan->exten, sizeof(trace->exten));
+		trace->priority = chan->priority;
+		AST_LIST_INSERT_HEAD(&traced->trace, trace, entry);
+	}
+	return 0;
+}
+
+/*! \brief Update the context backtrace if tracing is enabled */
+int ast_channel_trace_update(struct ast_channel *chan)
+{
+	struct ast_datastore *store = ast_channel_datastore_find(chan, &ast_chan_trace_datastore_info, NULL);
+	if (!store)
+		return 0;
+	return ast_channel_trace_data_update(chan, store->data);
+}
+
+/*! \brief Enable context tracing in the channel */
+int ast_channel_trace_enable(struct ast_channel *chan)
+{
+	struct ast_datastore *store = ast_channel_datastore_find(chan, &ast_chan_trace_datastore_info, NULL);
+	struct ast_chan_trace_data *traced;
+	if (!store) {
+		store = ast_channel_datastore_alloc(&ast_chan_trace_datastore_info, "ChanTrace");
+		if (!store) 
+			return -1;
+		traced = ast_calloc(1, sizeof(*traced));
+		if (!traced) {
+			ast_channel_datastore_free(store);
+			return -1;
+		}	
+		store->data = traced;
+		AST_LIST_HEAD_INIT_NOLOCK(&traced->trace);
+		ast_channel_datastore_add(chan, store);
+	}	
+	((struct ast_chan_trace_data *)store->data)->enabled = 1;
+	ast_channel_trace_data_update(chan, store->data);
+	return 0;
+}
+
+/*! \brief Disable context tracing in the channel */
+int ast_channel_trace_disable(struct ast_channel *chan)
+{
+	struct ast_datastore *store = ast_channel_datastore_find(chan, &ast_chan_trace_datastore_info, NULL);
+	if (!store)
+		return 0;
+	((struct ast_chan_trace_data *)store->data)->enabled = 0;
+	return 0;
+}
+#endif /* CHANNEL_TRACE */
 
 /*! \brief Checks to see if a channel is needing hang up */
 int ast_check_hangup(struct ast_channel *chan)

Modified: trunk/main/cli.c
URL: http://svn.digium.com/view/asterisk/trunk/main/cli.c?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/main/cli.c (original)
+++ trunk/main/cli.c Sun Feb 17 22:43:33 2008
@@ -987,6 +987,9 @@
 	char nf[256], wf[256], rf[256];
 	long elapsed_seconds=0;
 	int hour=0, min=0, sec=0;
+#ifdef CHANNEL_TRACE
+	int trace_enabled;
+#endif
 
 	switch (cmd) {
 	case CLI_INIT:
@@ -1071,7 +1074,12 @@
 		ast_cli(a->fd,"      Variables:\n%s\n", out->str);
 	if (c->cdr && ast_cdr_serialize_variables(c->cdr, &out, '=', '\n', 1))
 		ast_cli(a->fd,"  CDR Variables:\n%s\n", out->str);
-	
+#ifdef CHANNEL_TRACE
+	trace_enabled = ast_channel_trace_is_enabled(c);
+	ast_cli(a->fd, "  Context Trace: %s\n", trace_enabled ? "Enabled" : "Disabled");
+	if (trace_enabled && ast_channel_trace_serialize(c, &out))
+		ast_cli(a->fd, "          Trace:\n%s\n", out->str);
+#endif
 	ast_channel_unlock(c);
 	return CLI_SUCCESS;
 }

Modified: trunk/main/pbx.c
URL: http://svn.digium.com/view/asterisk/trunk/main/pbx.c?view=diff&rev=103754&r1=103753&r2=103754
==============================================================================
--- trunk/main/pbx.c (original)
+++ trunk/main/pbx.c Sun Feb 17 22:43:33 2008
@@ -2673,6 +2673,9 @@
 				ast_copy_string(c->exten, exten, sizeof(c->exten));
 			c->priority = priority;
 			pbx_substitute_variables(passdata, sizeof(passdata), c, e);
+#ifdef CHANNEL_TRACE
+			ast_channel_trace_update(c);
+#endif
 			ast_debug(1, "Launching '%s'\n", app->name);
 			if (VERBOSITY_ATLEAST(3)) {
 				char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];




More information about the asterisk-commits mailing list