[asterisk-commits] rmudgett: branch certified-11.2 r405481 - in /certified/branches/11.2: ./ app...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 14 12:30:18 CST 2014


Author: rmudgett
Date: Tue Jan 14 12:30:15 2014
New Revision: 405481

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=405481
Log:
verbosity: Fix performance of console verbose messages.

The per console verbose level feature as previously implemented caused a
large performance penalty.  The fix required some minor incompatibilities
if the new rasterisk is used to connect to an earlier version.  If the new
rasterisk connects to an older Asterisk version then the root console
verbose level is always affected by the "core set verbose" command of the
remote console even though it may appear to only affect the current
console.  If an older version of rasterisk connects to the new version
then the "core set verbose" command will have no effect.

* Fixed the verbose performance by not generating a verbose message if
nothing is going to use it and then filtered any generated verbose
messages before actually sending them to the remote consoles.

* Split the "core set debug" and "core set verbose" CLI commands to remove
the per module verbose support that cannot work with the per console
verbose level.

* Added a silent option to the "core set verbose" command.

* Fixed "core set debug off" tab completion.

* Made "core show settings" list the current console verbosity in addition
to the root console verbosity.

* Changed the default verbose level of the 'verbose' setting in the
logger.conf [logfiles] section.  The default is now to once again follow
the current root console level.  As a result, using the AMI Command action
with "core set verbose" could again set the root console verbose level and
affect the verbose level logged.

(closes issue AST-1252)
Reported by: Guenther Kelleter

Review: https://reviewboard.asterisk.org/r/3114/
........

Merged revisions 405431 from http://svn.asterisk.org/svn/asterisk/branches/11

Modified:
    certified/branches/11.2/   (props changed)
    certified/branches/11.2/UPGRADE.txt
    certified/branches/11.2/apps/app_dumpchan.c
    certified/branches/11.2/apps/app_verbose.c
    certified/branches/11.2/configs/logger.conf.sample
    certified/branches/11.2/funcs/func_timeout.c
    certified/branches/11.2/include/asterisk/logger.h
    certified/branches/11.2/main/asterisk.c
    certified/branches/11.2/main/cli.c
    certified/branches/11.2/main/logger.c
    certified/branches/11.2/main/manager.c
    certified/branches/11.2/main/pbx.c

Propchange: certified/branches/11.2/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Modified: certified/branches/11.2/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/UPGRADE.txt?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/UPGRADE.txt (original)
+++ certified/branches/11.2/UPGRADE.txt Tue Jan 14 12:30:15 2014
@@ -19,6 +19,32 @@
 === UPGRADE-10.txt -- Upgrade info for 1.8 to 10
 ===
 ===========================================================
+
+From 11.2-cert3 to 11.2-cert4:
+* The per console verbose level feature as previously implemented caused a
+  large performance penalty.  The fix required some minor incompatibilities
+  if the new rasterisk is used to connect to an earlier version.  If the new
+  rasterisk connects to an older Asterisk version then the root console verbose
+  level is always affected by the "core set verbose" command of the remote
+  console even though it may appear to only affect the current console.  If
+  an older version of rasterisk connects to the new version then the
+  "core set verbose" command will have no effect.
+
+CLI commands:
+ - "core show settings" now lists the current console verbosity in addition
+   to the root console verbosity.
+
+ - "core set verbose" has not been able to support the by module verbose
+   logging levels since verbose logging levels were made per console.  That
+   syntax is now removed and a silence option added in its place.
+
+Configuration Files:
+ - The 'verbose' setting in logger.conf still takes an optional argument,
+   specifying the verbosity level for each logging destination.  However,
+   the default is now to once again follow the current root console level.
+   As a result, using the AMI Command action with "core set verbose" could
+   again set the root console verbose level and affect the verbose level
+   logged.
 
 From 11.2-cert2 to 11.2-cert3:
 * Certain dialplan functions have been marked as 'dangerous', and may only be

Modified: certified/branches/11.2/apps/app_dumpchan.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/apps/app_dumpchan.c?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/apps/app_dumpchan.c (original)
+++ certified/branches/11.2/apps/app_dumpchan.c Tue Jan 14 12:30:15 2014
@@ -182,15 +182,17 @@
 	if (!ast_strlen_zero(data))
 		level = atoi(data);
 
-	serialize_showchan(chan, info, sizeof(info));
-	pbx_builtin_serialize_variables(chan, &vars);
-	ast_verb(level, "\n"
-		 "Dumping Info For Channel: %s:\n"
-		 "%s\n"
-		 "Info:\n"
-		 "%s\n"
-		 "Variables:\n"
-		 "%s%s\n", ast_channel_name(chan), line, info, ast_str_buffer(vars), line);
+	if (VERBOSITY_ATLEAST(level)) {
+		serialize_showchan(chan, info, sizeof(info));
+		pbx_builtin_serialize_variables(chan, &vars);
+		ast_verb(level, "\n"
+			"Dumping Info For Channel: %s:\n"
+			"%s\n"
+			"Info:\n"
+			"%s\n"
+			"Variables:\n"
+			"%s%s\n", ast_channel_name(chan), line, info, ast_str_buffer(vars), line);
+	}
 
 	return 0;
 }

Modified: certified/branches/11.2/apps/app_verbose.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/apps/app_verbose.c?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/apps/app_verbose.c (original)
+++ certified/branches/11.2/apps/app_verbose.c Tue Jan 14 12:30:15 2014
@@ -96,9 +96,11 @@
 		args.level = "0";
 	}
 
-	if (sscanf(args.level, "%30d", &vsize) != 1) {
+	if (sscanf(args.level, "%30u", &vsize) != 1) {
 		vsize = 0;
 		ast_log(LOG_WARNING, "'%s' is not a verboser number\n", args.level);
+	} else if (4 < vsize) {
+		vsize = 4;
 	}
 
 	ast_verb(vsize, "%s\n", args.msg);

Modified: certified/branches/11.2/configs/logger.conf.sample
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/configs/logger.conf.sample?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/configs/logger.conf.sample (original)
+++ certified/branches/11.2/configs/logger.conf.sample Tue Jan 14 12:30:15 2014
@@ -83,24 +83,25 @@
 ;    fax
 ;    security
 ;
-; Special filename "console" represents the system console
+; Special filename "console" represents the root console
 ;
 ; Filenames can either be relative to the standard Asterisk log directory
 ; (see 'astlogdir' in asterisk.conf), or absolute paths that begin with
 ; '/'.
 ;
+; Verbose takes an optional argument, in the form of an integer level.
+; Verbose messages with higher levels will not be logged to the file.  If
+; the verbose level is not specified, it will log verbose messages following
+; the current level of the root console.
+;
 ; Special level name "*" means all levels, even dynamic levels registered
 ; by modules after the logger has been initialized (this means that loading
 ; and unloading modules that create/remove dynamic logger levels will result
 ; in these levels being included on filenames that have a level name of "*",
-; without any need to perform a 'logger reload' or similar operation). Note
-; that there is no value in specifying both "*" and specific level names for
-; a filename; the "*" level means all levels, and the remaining level names
-; will be ignored.
-;
-; Verbose takes an additional argument, in the form of an integer level.
-; Messages with higher levels will be ignored.  If verbose is specified at
-; all, it will default to 3.
+; without any need to perform a 'logger reload' or similar operation).
+; Note that there is no value in specifying both "*" and specific level names
+; for a filename; the "*" level means all levels.  The only exception is if
+; you need to specify a specific verbose level. e.g, "verbose(3),*".
 ;
 ; We highly recommend that you DO NOT turn on debug mode if you are simply
 ; running a production system.  Debug mode turns on a LOT of extra messages,

Modified: certified/branches/11.2/funcs/func_timeout.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/funcs/func_timeout.c?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/funcs/func_timeout.c (original)
+++ certified/branches/11.2/funcs/func_timeout.c Tue Jan 14 12:30:15 2014
@@ -156,13 +156,15 @@
 	case 'a':
 	case 'A':
 		ast_channel_setwhentohangup_tv(chan, when);
-		if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
-			when = ast_tvadd(when, ast_tvnow());
-			ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",
-				ast_localtime(&when, &myt, NULL));
-			ast_verb(3, "Channel will hangup at %s.\n", timestr);
-		} else {
-			ast_verb(3, "Channel hangup cancelled.\n");
+		if (VERBOSITY_ATLEAST(3)) {
+			if (!ast_tvzero(*ast_channel_whentohangup(chan))) {
+				when = ast_tvadd(when, ast_tvnow());
+				ast_strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S.%3q %Z",
+					ast_localtime(&when, &myt, NULL));
+				ast_verb(3, "Channel will hangup at %s.\n", timestr);
+			} else {
+				ast_verb(3, "Channel hangup cancelled.\n");
+			}
 		}
 		break;
 

Modified: certified/branches/11.2/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/include/asterisk/logger.h?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/include/asterisk/logger.h (original)
+++ certified/branches/11.2/include/asterisk/logger.h Tue Jan 14 12:30:15 2014
@@ -87,21 +87,29 @@
 
 void __attribute__((format(printf, 5, 6))) ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...);
 
-/*! Send a verbose message (based on verbose level)
- *	\brief This works like ast_log, but prints verbose messages to the console depending on verbosity level set.
- *	ast_verbose(VERBOSE_PREFIX_3 "Whatever %s is happening\n", "nothing");
- *	This will print the message to the console if the verbose level is set to a level >= 3
- *	Note the absence of a comma after the VERBOSE_PREFIX_3.  This is important.
- *	VERBOSE_PREFIX_1 through VERBOSE_PREFIX_4 are defined.
- *  \version 11 added level parameter
+/*!
+ * \brief Send a verbose message (based on verbose level)
+ *
+ * \details This works like ast_log, but prints verbose messages to the console depending on verbosity level set.
+ *
+ * ast_verbose(VERBOSE_PREFIX_3 "Whatever %s is happening\n", "nothing");
+ *
+ * This will print the message to the console if the verbose level is set to a level >= 3
+ *
+ * Note the absence of a comma after the VERBOSE_PREFIX_3.  This is important.
+ * VERBOSE_PREFIX_1 through VERBOSE_PREFIX_4 are defined.
+ *
+ * \version 11 added level parameter
  */
 void __attribute__((format(printf, 5, 6))) __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
 
-/*! Send a verbose message (based on verbose level) with deliberately specified callid
- *  \brief just like __ast_verbose, only __ast_verbose_callid allows you to specify which callid is being used
- *  for the log without needing to bind it to a thread. NULL is a valid argument for this function and will
- *  allow you to specify that a log will never display a call id even when there is a call id bound to the
- *  thread.
+/*!
+ * \brief Send a verbose message (based on verbose level) with deliberately specified callid
+ *
+ * \details just like __ast_verbose, only __ast_verbose_callid allows you to specify which callid is being used
+ * for the log without needing to bind it to a thread. NULL is a valid argument for this function and will
+ * allow you to specify that a log will never display a call id even when there is a call id bound to the
+ * thread.
  */
 void __attribute__((format(printf, 6, 7))) __ast_verbose_callid(const char *file, int line, const char *func, int level, struct ast_callid *callid, const char *fmt, ...);
 
@@ -114,6 +122,14 @@
 
 int ast_register_verbose(void (*verboser)(const char *string)) attribute_warn_unused_result;
 int ast_unregister_verbose(void (*verboser)(const char *string)) attribute_warn_unused_result;
+
+/*
+ * These gymnastics are due to platforms which designate char as unsigned by
+ * default.  Level is the negative character -- offset by 1, because \0 is
+ * the string terminator.
+ */
+#define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1)
+#define VERBOSE_HASMAGIC(x)	(*(signed char *) (x) < 0)
 
 void ast_console_puts(const char *string);
 
@@ -222,8 +238,9 @@
  * \brief Get the verbose level for a module
  * \param module the name of module
  * \return the verbose level
- */
-unsigned int ast_verbose_get_by_module(const char *module);
+ * \version 11.0.0 deprecated
+ */
+unsigned int ast_verbose_get_by_module(const char *module) __attribute__((deprecated));
 
 /*!
  * \brief Register a new logger level
@@ -350,8 +367,62 @@
 		ast_log(AST_LOG_DEBUG, __VA_ARGS__); \
 } while (0)
 
-#define ast_verb(level, ...) __ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, __VA_ARGS__)
-#define ast_verb_callid(level, callid, ...) __ast_verbose_callid(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, callid, __VA_ARGS__)
+extern int ast_verb_sys_level;
+
+#define VERBOSITY_ATLEAST(level) ((level) <= ast_verb_sys_level)
+
+#define ast_verb(level, ...) \
+	do { \
+		if (VERBOSITY_ATLEAST(level) ) { \
+			__ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, __VA_ARGS__); \
+		} \
+	} while (0)
+
+#define ast_verb_callid(level, callid, ...) \
+	do { \
+		if (VERBOSITY_ATLEAST(level) ) { \
+			__ast_verbose_callid(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, callid, __VA_ARGS__); \
+		} \
+	} while (0)
+
+/*!
+ * \brief Re-evaluate the system max verbosity level (ast_verb_sys_level).
+ *
+ * \return Nothing
+ */
+void ast_verb_update(void);
+
+/*!
+ * \brief Register this thread's console verbosity level pointer.
+ *
+ * \param level Where the verbose level value is.
+ *
+ * \return Nothing
+ */
+void ast_verb_console_register(int *level);
+
+/*!
+ * \brief Unregister this thread's console verbosity level.
+ *
+ * \return Nothing
+ */
+void ast_verb_console_unregister(void);
+
+/*!
+ * \brief Get this thread's console verbosity level.
+ *
+ * \retval verbosity level of the console.
+ */
+int ast_verb_console_get(void);
+
+/*!
+ * \brief Set this thread's console verbosity level.
+ *
+ * \param verb_level New level to set.
+ *
+ * \return Nothing
+ */
+void ast_verb_console_set(int verb_level);
 
 #ifndef _LOGGER_BACKTRACE_H
 #define _LOGGER_BACKTRACE_H

Modified: certified/branches/11.2/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/main/asterisk.c?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/main/asterisk.c (original)
+++ certified/branches/11.2/main/asterisk.c Tue Jan 14 12:30:15 2014
@@ -191,6 +191,9 @@
 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
 struct ast_flags ast_compat = { 0 };
 
+/*! Maximum active system verbosity level. */
+int ast_verb_sys_level;
+
 int option_verbose;				/*!< Verbosity level */
 int option_debug;				/*!< Debug level */
 double option_maxload;				/*!< Max load avg on system */
@@ -219,6 +222,8 @@
 	int uid;			/*!< Remote user ID. */
 	int gid;			/*!< Remote group ID. */
 	int levels[NUMLOGLEVELS];	/*!< Which log levels are enabled for the console */
+	/*! Verbosity level of this console. */
+	int option_verbose;
 };
 
 struct ast_atexit {
@@ -480,7 +485,8 @@
 		ast_cli(a->fd, "  Maximum open file handles:   %d\n", option_maxfiles);
 	else
 		ast_cli(a->fd, "  Maximum open file handles:   Not set\n");
-	ast_cli(a->fd, "  Verbosity:                   %d\n", option_verbose);
+	ast_cli(a->fd, "  Root console verbosity:      %d\n", option_verbose);
+	ast_cli(a->fd, "  Current console verbosity:   %d\n", ast_verb_console_get());
 	ast_cli(a->fd, "  Debug level:                 %d\n", option_debug);
 	ast_cli(a->fd, "  Maximum load average:        %lf\n", option_maxload);
 #if defined(HAVE_SYSINFO)
@@ -1182,29 +1188,33 @@
 }
 
 /*!
- * \brief log the string to all attached console clients
+ * \brief log the string to all attached network console clients
  */
 static void ast_network_puts_mutable(const char *string, int level)
 {
 	int x;
-	for (x = 0;x < AST_MAX_CONNECTS; x++) {
-		if (consoles[x].mute)
+
+	for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+		if (consoles[x].fd < 0
+			|| consoles[x].mute
+			|| consoles[x].levels[level]) {
 			continue;
-		if (consoles[x].fd > -1) {
-			if (!consoles[x].levels[level])
-				fdprint(consoles[x].p[1], string);
-		}
+		}
+		fdprint(consoles[x].p[1], string);
 	}
 }
 
 /*!
- * \brief log the string to the console, and all attached
- * console clients
+ * \brief log the string to the root console, and all attached
+ * network console clients
  */
 void ast_console_puts_mutable(const char *string, int level)
 {
+	/* Send to the root console */
 	fputs(string, stdout);
 	fflush(stdout);
+
+	/* Send to any network console clients */
 	ast_network_puts_mutable(string, level);
 }
 
@@ -1214,26 +1224,45 @@
 static void ast_network_puts(const char *string)
 {
 	int x;
-	for (x = 0; x < AST_MAX_CONNECTS; x++) {
-		if (consoles[x].fd > -1)
-			fdprint(consoles[x].p[1], string);
+
+	for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+		if (consoles[x].fd < 0) {
+			continue;
+		}
+		fdprint(consoles[x].p[1], string);
 	}
 }
 
 /*!
- * write the string to the console, and all attached
- * console clients
+ * write the string to the root console, and all attached
+ * network console clients
  */
 void ast_console_puts(const char *string)
 {
+	/* Send to the root console */
 	fputs(string, stdout);
 	fflush(stdout);
+
+	/* Send to any network console clients */
 	ast_network_puts(string);
 }
 
-static void network_verboser(const char *s)
-{
-	ast_network_puts_mutable(s, __LOG_VERBOSE);
+static void network_verboser(const char *string)
+{
+	int x;
+	int verb_level;
+
+	/* Send to any network console clients if client verbocity allows. */
+	verb_level = VERBOSE_MAGIC2LEVEL(string);
+	for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+		if (consoles[x].fd < 0
+			|| consoles[x].mute
+			|| consoles[x].levels[__LOG_VERBOSE]
+			|| consoles[x].option_verbose < verb_level) {
+			continue;
+		}
+		fdprint(consoles[x].p[1], string);
+	}
 }
 
 static pthread_t lthread;
@@ -1297,6 +1326,7 @@
 	return result;
 }
 
+/* This is the thread running the remote console on the main process. */
 static void *netconsole(void *vconsole)
 {
 	struct console *con = vconsole;
@@ -1312,6 +1342,7 @@
 		ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
 	snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
 	fdprint(con->fd, outbuf);
+	ast_verb_console_register(&con->option_verbose);
 	for (;;) {
 		fds[0].fd = con->fd;
 		fds[0].events = POLLIN;
@@ -1374,6 +1405,7 @@
 				break;
 		}
 	}
+	ast_verb_console_unregister();
 	if (!ast_opt_hide_connect) {
 		ast_verb(3, "Remote UNIX connection disconnected\n");
 	}
@@ -1426,24 +1458,25 @@
 					}
 					if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
 						ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
-						consoles[x].fd = -1;
 						fdprint(s, "Server failed to create pipe\n");
 						close(s);
 						break;
 					}
 					flags = fcntl(consoles[x].p[1], F_GETFL);
 					fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
-					consoles[x].fd = s;
 					consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
 					/* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
 					   to know if the user didn't send the credentials. */
 					consoles[x].uid = -2;
 					consoles[x].gid = -2;
+					/* Server default of remote console verbosity level is OFF. */
+					consoles[x].option_verbose = 0;
+					consoles[x].fd = s;
 					if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
+						consoles[x].fd = -1;
 						ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
 						close(consoles[x].p[0]);
 						close(consoles[x].p[1]);
-						consoles[x].fd = -1;
 						fdprint(s, "Server failed to spawn thread\n");
 						close(s);
 					}
@@ -1930,12 +1963,6 @@
 
 AST_THREADSTORAGE_CUSTOM(console_state, console_state_init, ast_free_ptr);
 
-/* These gymnastics are due to platforms which designate char as unsigned by
- * default. Level is the negative character -- offset by 1, because \0 is the
- * EOS delimiter. */
-#define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1)
-#define VERBOSE_HASMAGIC(x)	(*(signed char *) (x) < 0)
-
 static int console_print(const char *s, int local)
 {
 	struct console_state_data *state =
@@ -2030,6 +2057,7 @@
 	return 1;
 }
 
+/* This is the main console CLI command handler.  Run by the main() thread. */
 static void consolehandler(char *s)
 {
 	printf("%s", term_end());
@@ -2062,38 +2090,56 @@
 		else
 			ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
 		ret = 1;
-	} else if (strncasecmp(s, "core set verbose ", 17) == 0) {
-		int old_verbose = option_verbose;
-		if (strncasecmp(s + 17, "atleast ", 8) == 0) {
-			int tmp;
-			if (sscanf(s + 25, "%d", &tmp) != 1) {
-				fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
-			} else {
-				if (tmp > option_verbose) {
-					option_verbose = tmp;
-				}
-				if (old_verbose != option_verbose) {
-					fprintf(stdout, "Set remote console verbosity from %d to %d\n", old_verbose, option_verbose);
-				} else {
-					fprintf(stdout, "Verbosity level unchanged.\n");
-				}
-			}
-		} else {
-			if (sscanf(s + 17, "%d", &option_verbose) != 1) {
-				fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
-			} else {
-				if (old_verbose != option_verbose) {
-					fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose);
-				} else {
-					fprintf(stdout, "Verbosity level unchanged.\n");
-				}
-			}
-		}
-		ret = 1;
 	} else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
 	    (s[4] == '\0' || isspace(s[4]))) {
 		quit_handler(0, SHUTDOWN_FAST, 0);
 		ret = 1;
+	} else if (s[0]) {
+		char *shrunk = ast_strdupa(s);
+		char *cur;
+		char *prev;
+
+		/*
+		 * Remove duplicate spaces from shrunk for matching purposes.
+		 *
+		 * shrunk has at least one character in it to start with or we
+		 * couldn't get here.
+		 */
+		for (prev = shrunk, cur = shrunk + 1; *cur; ++cur) {
+			if (*prev == ' ' && *cur == ' ') {
+				/* Skip repeated space delimiter. */
+				continue;
+			}
+			*++prev = *cur;
+		}
+		*++prev = '\0';
+
+		if (strncasecmp(shrunk, "core set verbose ", 17) == 0) {
+			/*
+			 * We need to still set the rasterisk option_verbose in case we are
+			 * talking to an earlier version which doesn't prefilter verbose
+			 * levels.  This is really a compromise as we should always take
+			 * whatever the server sends.
+			 */
+
+			if (!strncasecmp(shrunk + 17, "off", 3)) {
+				ast_verb_console_set(0);
+			} else {
+				int verbose_new;
+				int atleast;
+
+				atleast = 8;
+				if (strncasecmp(shrunk + 17, "atleast ", atleast)) {
+					atleast = 0;
+				}
+
+				if (sscanf(shrunk + 17 + atleast, "%30d", &verbose_new) == 1) {
+					if (!atleast || ast_verb_console_get() < verbose_new) {
+						ast_verb_console_set(verbose_new);
+					}
+				}
+			}
+		}
 	}
 
 	return ret;
@@ -2415,6 +2461,31 @@
 #endif /* ! LOW_MEMORY */
 };
 
+static void send_rasterisk_connect_commands(void)
+{
+	char buf[80];
+
+	/*
+	 * Tell the server asterisk instance about the verbose level
+	 * initially desired.
+	 */
+	if (option_verbose) {
+		snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
+		fdsend(ast_consock, buf);
+	}
+
+	if (option_debug) {
+		snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
+		fdsend(ast_consock, buf);
+	}
+
+	if (!ast_opt_mute) {
+		fdsend(ast_consock, "logger mute silent");
+	} else {
+		printf("log and verbose output currently muted ('logger mute' to unmute)\n");
+	}
+}
+
 static int ast_el_read_char(EditLine *editline, char *cp)
 {
 	int num_read = 0;
@@ -2468,10 +2539,7 @@
 							fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
 							printf("%s", term_quit());
 							WELCOME_MESSAGE;
-							if (!ast_opt_mute)
-								fdsend(ast_consock, "logger mute silent");
-							else
-								printf("log and verbose output currently muted ('logger mute' to unmute)\n");
+							send_rasterisk_connect_commands();
 							break;
 						} else
 							usleep(1000000 / reconnects_per_second);
@@ -2990,11 +3058,7 @@
 	else
 		pid = -1;
 	if (!data) {
-		if (!ast_opt_mute) {
-			fdsend(ast_consock, "logger mute silent");
-		} else {
-			printf("log and verbose output currently muted ('logger mute' to unmute)\n");
-		}
+		send_rasterisk_connect_commands();
 	}
 
 	if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
@@ -3467,6 +3531,7 @@
 		kill(canary_pid, SIGKILL);
 }
 
+/* Execute CLI commands on startup.  Run by main() thread. */
 static void run_startup_commands(void)
 {
 	int fd;
@@ -3895,6 +3960,9 @@
 		}
 	}
 
+	/* Initial value of the maximum active system verbosity level. */
+	ast_verb_sys_level = option_verbose;
+
 	if (ast_tryconnect()) {
 		/* One is already running */
 		if (ast_opt_remote) {

Modified: certified/branches/11.2/main/cli.c
URL: http://svnview.digium.com/svn/asterisk/certified/branches/11.2/main/cli.c?view=diff&rev=405481&r1=405480&r2=405481
==============================================================================
--- certified/branches/11.2/main/cli.c (original)
+++ certified/branches/11.2/main/cli.c Tue Jan 14 12:30:15 2014
@@ -94,8 +94,6 @@
 
 /*! list of module names and their debug levels */
 static struct module_level_list debug_modules;
-/*! list of module names and their verbose levels */
-static struct module_level_list verbose_modules;
 
 AST_THREADSTORAGE(ast_cli_buf);
 
@@ -139,19 +137,7 @@
 
 unsigned int ast_verbose_get_by_module(const char *module)
 {
-	struct module_level *ml;
-	unsigned int res = 0;
-
-	AST_RWLIST_RDLOCK(&verbose_modules);
-	AST_LIST_TRAVERSE(&verbose_modules, ml, entry) {
-		if (!strcasecmp(ml->module, module)) {
-			res = ml->level;
-			break;
-		}
-	}
-	AST_RWLIST_UNLOCK(&verbose_modules);
-
-	return res;
+	return 0;
 }
 
 /*! \internal
@@ -329,14 +315,19 @@
 
 	return CLI_SUCCESS;
 }
+
 /*!
- * \brief Find the debug or verbose file setting
- * \arg debug 1 for debug, 0 for verbose
+ * \brief Find the module level setting
+ *
+ * \param module Module name to look for.
+ * \param mll List to search.
+ *
+ * \retval level struct found on success.
+ * \retval NULL not found.
  */
-static struct module_level *find_module_level(const char *module, unsigned int debug)
+static struct module_level *find_module_level(const char *module, struct module_level_list *mll)
 {
 	struct module_level *ml;
-	struct module_level_list *mll = debug ? &debug_modules : &verbose_modules;
 
 	AST_LIST_TRAVERSE(mll, ml, entry) {
 		if (!strcasecmp(ml->module, module))
@@ -386,52 +377,77 @@
 	return NULL;
 }
 
-static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static void status_debug_verbose(struct ast_cli_args *a, const char *what, int old_val, int cur_val)
+{
+	char was_buf[30];
+	const char *was;
+
+	if (old_val) {
+		snprintf(was_buf, sizeof(was_buf), "%d", old_val);
+		was = was_buf;
+	} else {
+		was = "OFF";
+	}
+
+	if (old_val == cur_val) {
+		ast_cli(a->fd, "%s is still %s.\n", what, was);
+	} else {
+		char now_buf[30];
+		const char *now;
+
+		if (cur_val) {
+			snprintf(now_buf, sizeof(now_buf), "%d", cur_val);
+			now = now_buf;
+		} else {
+			now = "OFF";
+		}
+
+		ast_cli(a->fd, "%s was %s and is now %s.\n", what, was, now);
+	}
+}
+
+static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	int oldval;
 	int newlevel;
-	unsigned int is_debug;
 	int atleast = 0;
-	int fd = a->fd;
-	int argc = a->argc;
-	const char * const *argv = a->argv;
 	const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
-	int *dst;
-	char *what;
-	struct module_level_list *mll;
 	struct module_level *ml;
 
 	switch (cmd) {
 	case CLI_INIT:
-		e->command = "core set {debug|verbose}";
+		e->command = "core set debug";
 		e->usage =
 #if !defined(LOW_MEMORY)
-			"Usage: core set {debug|verbose} [atleast] <level> [module]\n"
+			"Usage: core set debug [atleast] <level> [module]\n"
 #else
-			"Usage: core set {debug|verbose} [atleast] <level>\n"
+			"Usage: core set debug [atleast] <level>\n"
 #endif
-			"       core set {debug|verbose} off\n"
+			"       core set debug off\n"
+			"\n"
 #if !defined(LOW_MEMORY)
-			"       Sets level of debug or verbose messages to be displayed or\n"
+			"       Sets level of debug messages to be displayed or\n"
 			"       sets a module name to display debug messages from.\n"
 #else
-			"       Sets level of debug or verbose messages to be displayed.\n"
+			"       Sets level of debug messages to be displayed.\n"
 #endif
-			"	0 or off means no messages should be displayed.\n"
-			"	Equivalent to -d[d[...]] or -v[v[v...]] on startup\n";
+			"       0 or off means no messages should be displayed.\n"
+			"       Equivalent to -d[d[...]] on startup\n";
 		return NULL;
 
 	case CLI_GENERATE:
-		if (a->pos == 3 || (a->pos == 4 && !strcasecmp(a->argv[3], "atleast"))) {
+		if (!strcasecmp(argv3, "atleast")) {
+			atleast = 1;
+		}
+		if (a->pos == 3 || (a->pos == 4 && atleast)) {
 			const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
 			int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
+
 			if (a->n < 21 && numbermatch == 0) {
 				return complete_number(pos, 0, 0x7fffffff, a->n);
 			} else if (pos[0] == '0') {
 				if (a->n == 0) {
 					return ast_strdup("0");
-				} else {
-					return NULL;
 				}
 			} else if (a->n == (21 - numbermatch)) {
 				if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
@@ -443,8 +459,11 @@
 				return ast_strdup("atleast");
 			}
 #if !defined(LOW_MEMORY)
-		} else if (a->pos == 4 || (a->pos == 5 && !strcasecmp(argv3, "atleast"))) {
-			return ast_complete_source_filename(a->pos == 4 ? S_OR(a->argv[4], "") : S_OR(a->argv[5], ""), a->n);
+		} else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
+			|| (a->pos == 5 && atleast)) {
+			const char *pos = S_OR(a->argv[a->pos], "");
+
+			return ast_complete_source_filename(pos, a->n);
 #endif
 		}
 		return NULL;
@@ -453,117 +472,200 @@
 	 * we are guaranteed to be called with argc >= e->args;
 	 */
 
-	if (argc <= e->args)
+	if (a->argc <= e->args) {
 		return CLI_SHOWUSAGE;
-	if (!strcasecmp(argv[e->args - 1], "debug")) {
-		dst = &option_debug;
-		oldval = option_debug;
-		what = "Core debug";
-		is_debug = 1;
+	}
+
+	if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
+		newlevel = 0;
 	} else {
-		dst = &option_verbose;
-		oldval = option_verbose;
-		what = "Verbosity";
-		is_debug = 0;
-	}
-	if (argc == e->args + 1 && !strcasecmp(argv[e->args], "off")) {
+		if (!strcasecmp(a->argv[e->args], "atleast")) {
+			atleast = 1;
+		}
+		if (a->argc != e->args + atleast + 1 && a->argc != e->args + atleast + 2) {
+			return CLI_SHOWUSAGE;
+		}
+		if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
+			return CLI_SHOWUSAGE;
+		}
+
+		if (a->argc == e->args + atleast + 2) {
+			/* We have specified a module name. */
+			char *mod = ast_strdupa(a->argv[e->args + atleast + 1]);
+			int mod_len = strlen(mod);
+
+			if (3 < mod_len && !strcasecmp(mod + mod_len - 3, ".so")) {
+				mod[mod_len - 3] = '\0';
+			}
+
+			AST_RWLIST_WRLOCK(&debug_modules);
+
+			ml = find_module_level(mod, &debug_modules);
+			if (!newlevel) {
+				if (!ml) {
+					/* Specified off for a nonexistent entry. */
+					AST_RWLIST_UNLOCK(&debug_modules);
+					ast_cli(a->fd, "Core debug is still 0 for '%s'.\n", mod);
+					return CLI_SUCCESS;
+				}
+				AST_RWLIST_REMOVE(&debug_modules, ml, entry);
+				if (AST_RWLIST_EMPTY(&debug_modules)) {
+					ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+				}
+				AST_RWLIST_UNLOCK(&debug_modules);
+				ast_cli(a->fd, "Core debug was %d and has been set to 0 for '%s'.\n",
+					ml->level, mod);
+				ast_free(ml);
+				return CLI_SUCCESS;
+			}
+
+			if (ml) {
+				if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
+					ast_cli(a->fd, "Core debug is still %d for '%s'.\n", ml->level, mod);
+					AST_RWLIST_UNLOCK(&debug_modules);
+					return CLI_SUCCESS;
+				}
+				oldval = ml->level;
+				ml->level = newlevel;
+			} else {
+				ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
+				if (!ml) {
+					AST_RWLIST_UNLOCK(&debug_modules);
+					return CLI_FAILURE;
+				}
+				oldval = ml->level;
+				ml->level = newlevel;
+				strcpy(ml->module, mod);
+				AST_RWLIST_INSERT_TAIL(&debug_modules, ml, entry);
+			}
+			ast_set_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+
+			ast_cli(a->fd, "Core debug was %d and has been set to %d for '%s'.\n",
+				oldval, ml->level, ml->module);
+
+			AST_RWLIST_UNLOCK(&debug_modules);
+
+			return CLI_SUCCESS;
+		}
+	}
+
+	/* Update global debug level */
+	if (!newlevel) {
+		/* Specified level was 0 or off. */
+		AST_RWLIST_WRLOCK(&debug_modules);
+		while ((ml = AST_RWLIST_REMOVE_HEAD(&debug_modules, entry))) {
+			ast_free(ml);
+		}
+		ast_clear_flag(&ast_options, AST_OPT_FLAG_DEBUG_MODULE);
+		AST_RWLIST_UNLOCK(&debug_modules);
+	}
+	oldval = option_debug;
+	if (!atleast || newlevel > option_debug) {
+		option_debug = newlevel;
+	}
+
+	/* Report debug level status */
+	status_debug_verbose(a, "Core debug", oldval, option_debug);
+
+	return CLI_SUCCESS;
+}
+
+static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	int oldval;
+	int newlevel;
+	int atleast = 0;
+	int silent = 0;
+	const char *argv3 = a->argv ? S_OR(a->argv[3], "") : "";
+
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "core set verbose";
+		e->usage =
+			"Usage: core set verbose [atleast] <level> [silent]\n"
+			"       core set verbose off\n"
+			"\n"
+			"       Sets level of verbose messages to be displayed.\n"
+			"       0 or off means no verbose messages should be displayed.\n"
+			"       The silent option means the command does not report what\n"
+			"       happened to the verbose level.\n"
+			"       Equivalent to -v[v[...]] on startup\n";
+		return NULL;
+
+	case CLI_GENERATE:
+		if (!strcasecmp(argv3, "atleast")) {
+			atleast = 1;
+		}
+		if (a->pos == 3 || (a->pos == 4 && atleast)) {
+			const char *pos = a->pos == 3 ? argv3 : S_OR(a->argv[4], "");
+			int numbermatch = (ast_strlen_zero(pos) || strchr("123456789", pos[0])) ? 0 : 21;
+
+			if (a->n < 21 && numbermatch == 0) {
+				return complete_number(pos, 0, 0x7fffffff, a->n);
+			} else if (pos[0] == '0') {
+				if (a->n == 0) {
+					return ast_strdup("0");
+				}
+			} else if (a->n == (21 - numbermatch)) {
+				if (a->pos == 3 && !strncasecmp(argv3, "off", strlen(argv3))) {
+					return ast_strdup("off");
+				} else if (a->pos == 3 && !strncasecmp(argv3, "atleast", strlen(argv3))) {
+					return ast_strdup("atleast");
+				}
+			} else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
+				return ast_strdup("atleast");
+			}
+		} else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off"))
+			|| (a->pos == 5 && atleast)) {
+			const char *pos = S_OR(a->argv[a->pos], "");
+
+			if (a->n == 0 && !strncasecmp(pos, "silent", strlen(pos))) {
+				return ast_strdup("silent");
+			}
+		}
+		return NULL;
+	}
+	/* all the above return, so we proceed with the handler.
+	 * we are guaranteed to be called with argc >= e->args;
+	 */
+
+	if (a->argc <= e->args) {
+		return CLI_SHOWUSAGE;
+	}
+
+	if (a->argc == e->args + 1 && !strcasecmp(a->argv[e->args], "off")) {
 		newlevel = 0;
-
-		mll = is_debug ? &debug_modules : &verbose_modules;
-
-		AST_RWLIST_WRLOCK(mll);
-		while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
-			ast_free(ml);
-		}
-		ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
-		AST_RWLIST_UNLOCK(mll);
-
-		goto done;
-	}
-	if (!strcasecmp(argv[e->args], "atleast"))
-		atleast = 1;
-	if (argc != e->args + atleast + 1 && argc != e->args + atleast + 2)
-		return CLI_SHOWUSAGE;
-	if (sscanf(argv[e->args + atleast], "%30d", &newlevel) != 1)
-		return CLI_SHOWUSAGE;
-	if (argc == e->args + atleast + 2) {
-		/* We have specified a module name. */
-		char *mod = ast_strdupa(argv[e->args + atleast + 1]);
-
-		if ((strlen(mod) > 3) && !strcasecmp(mod + strlen(mod) - 3, ".so")) {
-			mod[strlen(mod) - 3] = '\0';
-		}
-
-		mll = is_debug ? &debug_modules : &verbose_modules;
-
-		AST_RWLIST_WRLOCK(mll);
-
-		ml = find_module_level(mod, is_debug);
-		if (!newlevel) {
-			if (!ml) {
-				/* Specified off for a nonexistent entry. */
-				AST_RWLIST_UNLOCK(mll);
-				return CLI_SUCCESS;
-			}
-			AST_RWLIST_REMOVE(mll, ml, entry);
-			if (AST_RWLIST_EMPTY(mll))
-				ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
-			AST_RWLIST_UNLOCK(mll);
-			ast_cli(fd, "%s was %d and has been set to 0 for '%s'\n", what, ml->level, mod);
-			ast_free(ml);
-			return CLI_SUCCESS;
-		}
-
-		if (ml) {
-			if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
-				ast_cli(fd, "%s is %d for '%s'\n", what, ml->level, mod);
-				AST_RWLIST_UNLOCK(mll);
-				return CLI_SUCCESS;
-			}
-			oldval = ml->level;
-			ml->level = newlevel;
-		} else {
-			ml = ast_calloc(1, sizeof(*ml) + strlen(mod) + 1);
-			if (!ml) {
-				AST_RWLIST_UNLOCK(mll);
-				return CLI_FAILURE;
-			}
-			oldval = ml->level;
-			ml->level = newlevel;
-			strcpy(ml->module, mod);
-			AST_RWLIST_INSERT_TAIL(mll, ml, entry);
-		}
-
-		ast_set_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
-
-		AST_RWLIST_UNLOCK(mll);
-
-		ast_cli(fd, "%s was %d and has been set to %d for '%s'\n", what, oldval, ml->level, ml->module);
-
+	} else {
+		if (!strcasecmp(a->argv[e->args], "atleast")) {
+			atleast = 1;
+		}
+		if (a->argc == e->args + atleast + 2
+			&& !strcasecmp(a->argv[e->args + atleast + 1], "silent")) {
+			silent = 1;
+		}
+		if (a->argc != e->args + atleast + silent + 1) {
+			return CLI_SHOWUSAGE;
+		}
+		if (sscanf(a->argv[e->args + atleast], "%30d", &newlevel) != 1) {
+			return CLI_SHOWUSAGE;
+		}
+	}
+
+	/* Update verbose level */
+	oldval = ast_verb_console_get();
+	if (!atleast || newlevel > oldval) {
+		ast_verb_console_set(newlevel);
+	} else {
+		newlevel = oldval;
+	}
+
+	if (silent) {
+		/* Be silent after setting the level. */
 		return CLI_SUCCESS;
-	} else if (!newlevel) {
-		/* Specified level as 0 instead of off. */
-		mll = is_debug ? &debug_modules : &verbose_modules;
-
-		AST_RWLIST_WRLOCK(mll);
-		while ((ml = AST_RWLIST_REMOVE_HEAD(mll, entry))) {
-			ast_free(ml);
-		}
-		ast_clear_flag(&ast_options, is_debug ? AST_OPT_FLAG_DEBUG_MODULE : AST_OPT_FLAG_VERBOSE_MODULE);
-		AST_RWLIST_UNLOCK(mll);
-	}
-

[... 382 lines stripped ...]



More information about the asterisk-commits mailing list