[openib-general] [PATCHv2] osm: Dynamic verbosity control per file

Yevgeny Kliteynik kliteyn at mellanox.co.il
Sun Aug 27 07:49:09 PDT 2006


Hi Hal.

This is a resubmission of the patch that addresses 
the comments that I got on the first version - using 
osm-log.conf file instead of opensmlog.conf and osm 
man page update.

Yevgeny

Signed-off-by:  Yevgeny Kliteynik <kliteyn at mellanox.co.il>

Index: include/opensm/osm_subnet.h
===================================================================
--- include/opensm/osm_subnet.h	(revision 9107)
+++ include/opensm/osm_subnet.h	(working copy)
@@ -285,6 +285,8 @@ typedef struct _osm_subn_opt
   osm_qos_options_t        qos_sw0_options;
   osm_qos_options_t        qos_swe_options;
   osm_qos_options_t        qos_rtr_options;
+  boolean_t                src_info;
+  char *                   verbosity_file;
 } osm_subn_opt_t;
 /*
 * FIELDS
@@ -463,6 +465,27 @@ typedef struct _osm_subn_opt
 *	qos_rtr_options
 *		QoS options for router ports
 *
+*	src_info
+*		If TRUE - the source code filename and line number will be 
+*       added to each log message.
+*		Default value - FALSE.
+*
+*	verbosity_file
+*       OSM log configuration file - the file that describes 
+*       verbosity level per source code file.   
+*       The file may containg zero or more lines of the following
+*       pattern:
+*          filename verbosity_level
+*       where 'filename' is the name of the source code file that 
+*       the 'verbosity_level' refers to.
+*       Filename "all" represents general verbosity level, that is
+*       used for all the files that are not specified in the 
+*       verbosity file.
+*       If "all" is not specified, the general verbosity level will
+*       be used instead.
+*       Note: the "all" file verbosity level will override any other
+*       general level that was specified by the command line arguments. 
+*
 * SEE ALSO
 *	Subnet object
 *********/
Index: include/opensm/osm_base.h
===================================================================
--- include/opensm/osm_base.h	(revision 9107)
+++ include/opensm/osm_base.h	(working copy)
@@ -222,6 +222,22 @@ BEGIN_C_DECLS
 #endif
 /***********/
 
+/****d* OpenSM: Base/OSM_DEFAULT_VERBOSITY_FILE
+* NAME
+*	OSM_DEFAULT_VERBOSITY_FILE
+*
+* DESCRIPTION
+*	Specifies the default verbosity config file name
+*
+* SYNOPSIS
+*/
+#ifdef __WIN__
+#define OSM_DEFAULT_VERBOSITY_FILE strcat(GetOsmPath(), "osm-log.conf")
+#else
+#define OSM_DEFAULT_VERBOSITY_FILE "/etc/osm-log.conf"
+#endif
+/***********/
+
 /****d* OpenSM: Base/OSM_DEFAULT_PARTITION_CONFIG_FILE
 * NAME
 *	OSM_DEFAULT_PARTITION_CONFIG_FILE
Index: include/opensm/osm_log.h
===================================================================
--- include/opensm/osm_log.h	(revision 9107)
+++ include/opensm/osm_log.h	(working copy)
@@ -57,6 +57,7 @@
 #include <complib/cl_log.h>
 #include <complib/cl_spinlock.h>
 #include <opensm/osm_base.h>
+#include <opensm/st.h>
 #include <iba/ib_types.h>
 #include <stdio.h>
 
@@ -123,9 +124,45 @@ typedef struct _osm_log
 	cl_spinlock_t			lock;
 	boolean_t			flush;
 	FILE*				out_port;
+    boolean_t        src_info;
+    st_table *       table;
 } osm_log_t;
 /*********/
 
+/****f* OpenSM: Log/osm_log_read_verbosity_file
+* NAME
+*	osm_log_read_verbosity_file
+*
+* DESCRIPTION
+*	This function reads the verbosity configuration file
+*   and constructs a verbosity data structure.
+*
+* SYNOPSIS
+*/
+void
+osm_log_read_verbosity_file(
+    IN osm_log_t* p_log,
+    IN const char * const verbosity_file);
+/*
+* PARAMETERS
+*	p_log
+*		[in] Pointer to a Log object to construct.
+* 
+*	verbosity_file
+*		[in] verbosity configuration file
+*
+* RETURN VALUE
+*	  None
+*
+* NOTES
+*     If the verbosity configuration file is not found, default
+*     verbosity value is used for all files.
+*     If there is an error in some line of the verbosity
+*     configuration file, the line is ignored.
+*
+*********/
+
+
 /****f* OpenSM: Log/osm_log_construct
 * NAME
 *	osm_log_construct
@@ -201,9 +238,13 @@ osm_log_destroy(
 *	osm_log_init
 *********/
 
-/****f* OpenSM: Log/osm_log_init
+#define osm_log_init(p_log, flush, log_flags, log_file, accum_log_file) \
+      osm_log_init_ext(p_log, flush, (log_flags), log_file, \
+      accum_log_file, FALSE, OSM_DEFAULT_VERBOSITY_FILE)
+
+/****f* OpenSM: Log/osm_log_init_ext
 * NAME
-*	osm_log_init
+*	osm_log_init_ext
 *
 * DESCRIPTION
 *	The osm_log_init function initializes a
@@ -211,50 +252,15 @@ osm_log_destroy(
 *
 * SYNOPSIS
 */
-static inline ib_api_status_t
-osm_log_init(
+ib_api_status_t
+osm_log_init_ext(
   IN osm_log_t* const p_log,
   IN const boolean_t flush,
   IN const uint8_t log_flags,
   IN const char *log_file,
-  IN const boolean_t accum_log_file )
-{
-  p_log->level = log_flags;
-  p_log->flush = flush;
-
-  if (log_file == NULL || !strcmp(log_file, "-") ||
-      !strcmp(log_file, "stdout"))
-  {
-    p_log->out_port = stdout;
-  }
-  else if (!strcmp(log_file, "stderr"))
-  {
-    p_log->out_port = stderr;
-  }
-  else
-  {
-    if (accum_log_file)
-      p_log->out_port = fopen(log_file, "a+");
-    else
-      p_log->out_port = fopen(log_file, "w+");
-
-    if (!p_log->out_port)
-    {
-      if (accum_log_file)
-        printf("Cannot open %s for appending. Permission denied\n", log_file);
-      else
-        printf("Cannot open %s for writing. Permission denied\n", log_file);
-
-      return(IB_UNKNOWN_ERROR);
-    }
-  }
-  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
-
-  if (cl_spinlock_init( &p_log->lock ) == CL_SUCCESS) 
-    return IB_SUCCESS;
-  else
-    return IB_ERROR;
-}
+  IN const boolean_t accum_log_file,
+  IN const boolean_t src_info,
+  IN const char *verbosity_file);
 /*
 * PARAMETERS
 *	p_log
@@ -271,6 +277,16 @@ osm_log_init(
 *  log_file
 *     [in] if not NULL defines the name of the log file. Otherwise it is stdout.
 *
+*  accum_log_file
+*     [in] Whether the log file should be accumulated.
+*
+*  src_info
+*     [in] Set to TRUE directs the log to add filename and line number
+*     to each log message.
+*
+*  verbosity_file
+*     [in] Log configuration file location.
+*
 * RETURN VALUES
 *	CL_SUCCESS if the Log object was initialized
 *	successfully.
@@ -283,25 +299,31 @@ osm_log_init(
 *	osm_log_destroy
 *********/
 
-/****f* OpenSM: Log/osm_log_get_level
+#define osm_log_get_level(p_log) \
+      osm_log_get_level_ext(p_log, __FILE__)
+
+/****f* OpenSM: Log/osm_log_get_level_ext
 * NAME
-*	osm_log_get_level
+*	osm_log_get_level_ext
 *
 * DESCRIPTION
-*	Returns the current log level.
+*	Returns the current log level for the file.
+*	If the file is not specified in the log config file,
+*	the general verbosity level will be returned.
 *
 * SYNOPSIS
 */
-static inline osm_log_level_t
-osm_log_get_level(
-	IN const osm_log_t* const p_log )
-{
-	return( p_log->level );
-}
+osm_log_level_t
+osm_log_get_level_ext(
+	IN const osm_log_t* const p_log,
+	IN const char* const p_filename );
 /*
 * PARAMETERS
 *	p_log
 *		[in] Pointer to the log object.
+* 
+*	p_filename
+*		[in] Source code file name.
 *
 * RETURN VALUES
 *	Returns the current log level.
@@ -310,7 +332,7 @@ osm_log_get_level(
 *
 * SEE ALSO
 *	Log object, osm_log_construct,
-*	osm_log_destroy
+*	osm_log_destroy, osm_log_get_level
 *********/
 
 /****f* OpenSM: Log/osm_log_set_level
@@ -318,7 +340,7 @@ osm_log_get_level(
 *	osm_log_set_level
 *
 * DESCRIPTION
-*	Sets the current log level.
+*	Sets the current general log level.
 *
 * SYNOPSIS
 */
@@ -338,7 +360,7 @@ osm_log_set_level(
 *		[in] New level to set.
 *
 * RETURN VALUES
-*	Returns the current log level.
+*	None.
 *
 * NOTES
 *
@@ -347,9 +369,12 @@ osm_log_set_level(
 *	osm_log_destroy
 *********/
 
-/****f* OpenSM: Log/osm_log_is_active
+#define osm_log_is_active(p_log, level)  \
+      osm_log_is_active_ext(p_log, __FILE__, level)
+
+/****f* OpenSM: Log/osm_log_is_active_ext
 * NAME
-*	osm_log_is_active
+*	osm_log_is_active_ext
 *
 * DESCRIPTION
 *	Returns TRUE if the specified log level would be logged.
@@ -357,18 +382,19 @@ osm_log_set_level(
 *
 * SYNOPSIS
 */
-static inline boolean_t
-osm_log_is_active(
+boolean_t
+osm_log_is_active_ext(
 	IN const osm_log_t* const p_log,
-	IN const osm_log_level_t level )
-{
-	return( (p_log->level & level) != 0 );
-}
+	IN const char* const p_filename,
+	IN const osm_log_level_t level );
 /*
 * PARAMETERS
 *	p_log
 *		[in] Pointer to the log object.
 *
+*	p_filename
+*		[in] Source code file name.
+*
 *	level
 *		[in] Level to check.
 *
@@ -383,17 +409,125 @@ osm_log_is_active(
 *	osm_log_destroy
 *********/
 
+
+#define osm_log(p_log, verbosity, p_str, args...) \
+      osm_log_ext(p_log, verbosity, __FILE__, __LINE__, p_str , ## args)
+
+/****f* OpenSM: Log/osm_log_ext
+* NAME
+*	osm_log_ext
+*
+* DESCRIPTION
+*	Logs the formatted specified message.
+*
+* SYNOPSIS
+*/
 void
-osm_log(
+osm_log_ext(
 	IN osm_log_t* const p_log,
 	IN const osm_log_level_t verbosity,
+	IN const char *p_filename,
+	IN int line,
 	IN const char *p_str, ... );
+/*
+* PARAMETERS
+*	p_log
+*		[in] Pointer to the log object.
+*
+*	verbosity
+*		[in] Current message verbosity level
+
+	p_filename
+		[in] Name of the file that is logging this message
+
+	line
+		[in] Line number in the file that is logging this message
 
+	p_str
+		[in] Format string of the message
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	Log object, osm_log_construct,
+*	osm_log_destroy
+*********/
+
+#define osm_log_raw(p_log, verbosity, p_buff) \
+      osm_log_raw_ext(p_log, verbosity, __FILE__, p_buff)
+
+/****f* OpenSM: Log/osm_log_raw_ext
+* NAME
+*	osm_log_ext
+*
+* DESCRIPTION
+*	Logs the specified message.
+*
+* SYNOPSIS
+*/
 void
-osm_log_raw(
+osm_log_raw_ext(
 	IN osm_log_t* const p_log,
 	IN const osm_log_level_t verbosity,
+	IN const char * p_filename,
 	IN const char *p_buf );
+/*
+* PARAMETERS
+*	p_log
+*		[in] Pointer to the log object.
+*
+*	verbosity
+*		[in] Current message verbosity level
+
+	p_filename
+		[in] Name of the file that is logging this message
+
+	p_buf
+		[in] Message string
+*
+* RETURN VALUES
+*	None.
+*
+* NOTES
+*
+* SEE ALSO
+*	Log object, osm_log_construct,
+*	osm_log_destroy
+*********/
+
+
+/****f* OpenSM: Log/osm_log_flush
+* NAME
+*   osm_log_flush
+*
+* DESCRIPTION
+*   Flushes the log.
+*
+* SYNOPSIS
+*/
+static inline void
+osm_log_flush(
+	IN osm_log_t* const p_log)
+{
+   fflush(p_log->out_port);
+}
+/*
+* PARAMETERS
+*   p_log
+*      [in] Pointer to the log object.
+*
+* RETURN VALUES
+*   None.
+*
+* NOTES
+*
+* SEE ALSO
+*
+*********/
+
 
 #define DBG_CL_LOCK 0
 
Index: opensm/osm_subnet.c
===================================================================
--- opensm/osm_subnet.c	(revision 9107)
+++ opensm/osm_subnet.c	(working copy)
@@ -493,6 +493,8 @@ osm_subn_set_default_opt(
   p_opt->ucast_dump_file = NULL;
   p_opt->updn_guid_file = NULL;
   p_opt->exit_on_fatal = TRUE;
+  p_opt->src_info = FALSE;
+  p_opt->verbosity_file = OSM_DEFAULT_VERBOSITY_FILE;
   subn_set_default_qos_options(&p_opt->qos_options);
   subn_set_default_qos_options(&p_opt->qos_hca_options);
   subn_set_default_qos_options(&p_opt->qos_sw0_options);
@@ -959,6 +961,13 @@ osm_subn_parse_conf_file(
         "honor_guid2lid_file",
         p_key, p_val, &p_opts->honor_guid2lid_file);
 
+      __osm_subn_opts_unpack_boolean(
+        "log_source_info",
+        p_key, p_val, &p_opts->src_info);
+
+      __osm_subn_opts_unpack_charp(
+        "verbosity_file", p_key, p_val, &p_opts->verbosity_file);
+
       subn_parse_qos_options("qos",
         p_key, p_val, &p_opts->qos_options);
 
@@ -1182,7 +1191,11 @@ osm_subn_write_conf_file(
     "# No multicast routing is performed if TRUE\n"
     "disable_multicast %s\n\n"
     "# If TRUE opensm will exit on fatal initialization issues\n"
-    "exit_on_fatal %s\n\n",
+    "exit_on_fatal %s\n\n"
+    "# If TRUE OpenSM will log filename and line numbers\n"
+    "log_source_info %s\n\n"
+    "# Verbosity configuration file to be used\n"
+    "verbosity_file %s\n\n",
     p_opts->log_flags,
     p_opts->force_log_flush ? "TRUE" : "FALSE",
     p_opts->log_file,
@@ -1190,7 +1203,9 @@ osm_subn_write_conf_file(
     p_opts->dump_files_dir,
     p_opts->no_multicast_option ? "TRUE" : "FALSE",
     p_opts->disable_multicast ? "TRUE" : "FALSE",
-    p_opts->exit_on_fatal ? "TRUE" : "FALSE"
+    p_opts->exit_on_fatal ? "TRUE" : "FALSE",
+    p_opts->src_info ? "TRUE" : "FALSE",
+    p_opts->verbosity_file
     );
   
   fprintf(
Index: opensm/osm_opensm.c
===================================================================
--- opensm/osm_opensm.c	(revision 9107)
+++ opensm/osm_opensm.c	(working copy)
@@ -180,8 +180,10 @@ osm_opensm_init(
    /* Can't use log macros here, since we're initializing the log. */
    osm_opensm_construct( p_osm );
 
-   status = osm_log_init( &p_osm->log, p_opt->force_log_flush,
-                          p_opt->log_flags, p_opt->log_file, p_opt->accum_log_file );
+   status = osm_log_init_ext( &p_osm->log, p_opt->force_log_flush,
+                          p_opt->log_flags, p_opt->log_file,
+                          p_opt->accum_log_file, p_opt->src_info, 
+                          p_opt->verbosity_file);
    if( status != IB_SUCCESS )
       return ( status );
 
Index: opensm/libopensm.map
===================================================================
--- opensm/libopensm.map	(revision 9107)
+++ opensm/libopensm.map	(working copy)
@@ -1,6 +1,11 @@
-OPENSM_1.1 {
+OPENSM_2.0 {
 	global:
-		osm_log;
+		osm_log_init_ext;
+		osm_log_ext;
+		osm_log_raw_ext;
+		osm_log_get_level_ext;
+		osm_log_is_active_ext;
+		osm_log_read_verbosity_file;
 		osm_is_debug;
 		osm_mad_pool_construct;
 		osm_mad_pool_destroy;
@@ -39,7 +44,6 @@ OPENSM_1.1 {
 		osm_dump_dr_path;
 		osm_dump_smp_dr_path;
 		osm_dump_pkey_block;
-		osm_log_raw;
 		osm_get_sm_state_str;
 		osm_get_sm_signal_str;
 		osm_get_disp_msg_str;
@@ -51,5 +55,11 @@ OPENSM_1.1 {
 		osm_get_lsa_str;
 		osm_get_sm_mgr_signal_str;
 		osm_get_sm_mgr_state_str;
+		st_init_strtable;
+		st_delete;
+		st_insert;
+		st_lookup;
+		st_foreach;
+		st_free_table;
 	local: *;
 };
Index: opensm/osm_log.c
===================================================================
--- opensm/osm_log.c	(revision 9107)
+++ opensm/osm_log.c	(working copy)
@@ -81,98 +81,465 @@ static char *month_str[] = {
 };
 #endif /* ndef WIN32 */
 
-static int log_exit_count = 0;
 
-void
-osm_log(
-  IN osm_log_t* const p_log,
-  IN const osm_log_level_t verbosity,
-  IN const char *p_str, ... )
-{
-  char      buffer[LOG_ENTRY_SIZE_MAX];
-  va_list   args;
-  int       ret;
+/***************************************************************************
+ ***************************************************************************/
 
-#ifdef WIN32
-  SYSTEMTIME st;
-  uint32_t pid = GetCurrentThreadId();
-#else
-  pid_t pid = 0;
-  time_t tim;
-  struct tm result;
-  uint64_t time_usecs;
-  uint32_t usecs;
-
-  time_usecs = cl_get_time_stamp();
-  tim = time_usecs/1000000;
-  usecs = time_usecs % 1000000;
-  localtime_r(&tim, &result);
-#endif /* WIN32 */
+#define OSM_VERBOSITY_ALL "all"
+
+static void
+__osm_log_free_verbosity_table(
+           IN osm_log_t* p_log);
+static void
+__osm_log_print_verbosity_table(
+           IN osm_log_t* const p_log);
+
+/***************************************************************************
+ ***************************************************************************/
+
+osm_log_level_t
+osm_log_get_level_ext(
+           IN const osm_log_t* const p_log,
+           IN const char* const p_filename )
+{
+   osm_log_level_t * p_curr_file_level = NULL;
+
+   if (!p_filename || !p_log->table)
+      return p_log->level;
+
+   if ( st_lookup( p_log->table, 
+                  (st_data_t) p_filename, 
+                  (st_data_t*) &p_curr_file_level) )
+      return *p_curr_file_level;
+   else
+      return p_log->level;
+}
+
+/***************************************************************************
+ ***************************************************************************/
 
-  /* If this is a call to syslog - always print it */
-  if ( verbosity & OSM_LOG_SYS )
+ib_api_status_t
+osm_log_init_ext(
+           IN osm_log_t* const p_log,
+           IN const boolean_t flush,
+           IN const uint8_t log_flags,
+           IN const char *log_file,
+           IN const boolean_t accum_log_file,
+           IN const boolean_t src_info,
+           IN const char *verbosity_file)
+{
+  p_log->level = log_flags;
+  p_log->flush = flush;
+  p_log->src_info = src_info;
+  p_log->table = NULL;
+
+  if (log_file == NULL || !strcmp(log_file, "-") ||
+      !strcmp(log_file, "stdout"))
+  {
+    p_log->out_port = stdout;
+  }
+  else if (!strcmp(log_file, "stderr"))
+  {
+    p_log->out_port = stderr;
+  }
+  else
   {
-    /* this is a call to the syslog */
-    va_start( args, p_str );
-    vsprintf( buffer, p_str, args );
-    va_end(args);
-    cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
+    if (accum_log_file)
+      p_log->out_port = fopen(log_file, "a+");
+    else
+      p_log->out_port = fopen(log_file, "w+");
 
-    /* SYSLOG should go to stdout too */
-    if (p_log->out_port != stdout)
+    if (!p_log->out_port)
     {
-      printf("%s\n", buffer);
-      fflush( stdout );
+      if (accum_log_file)
+        printf("Cannot open %s for appending. Permission denied\n", log_file);
+      else
+        printf("Cannot open %s for writing. Permission denied\n", log_file);
+
+      return(IB_UNKNOWN_ERROR);
     }
+  }
+  openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
+
+  if (cl_spinlock_init( &p_log->lock ) != CL_SUCCESS)
+    return IB_ERROR;
+  
+  osm_log_read_verbosity_file(p_log,verbosity_file);
+  return IB_SUCCESS;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+void
+osm_log_read_verbosity_file(
+           IN osm_log_t* p_log,
+           IN const char * const verbosity_file)
+{
+   FILE *infile;
+   char line[500];
+   struct stat buf;
+   boolean_t table_empty = TRUE;
+   char * tmp_str = NULL;
+
+   if (p_log->table)
+   {
+      /*
+       * Free the existing table.
+       * Note: if the verbosity config file will not be found, this will
+       * effectivly reset the existing verbosity configuration and set
+       * all the files to the same verbosity level
+       */
+      __osm_log_free_verbosity_table(p_log);
+   }
+
+   if (!verbosity_file)
+      return;
+
+   if ( stat(verbosity_file, &buf) != 0 )
+   {
+      /*
+       * Verbosity configuration file doesn't exist.
+       */
+      if (strcmp(verbosity_file,OSM_DEFAULT_VERBOSITY_FILE) == 0)
+      {
+         /*
+          * Verbosity configuration file wasn't explicitly specified.
+          * No need to issue any error message.
+          */
+         return;
+      }
+      else
+      {
+         /*
+          * Verbosity configuration file was explicitly specified.
+          */
+         osm_log(p_log, OSM_LOG_SYS, 
+                 "ERROR: Verbosity configuration file (%s) doesn't exist.\n",
+                 verbosity_file);
+         osm_log(p_log, OSM_LOG_SYS, 
+                 "       Using general verbosity value.\n");
+         return;
+      }
+   }
+
+   infile = fopen(verbosity_file, "r");
+   if ( infile == NULL )
+   {
+      osm_log(p_log, OSM_LOG_SYS, 
+              "ERROR: Failed opening verbosity configuration file (%s).\n",
+              verbosity_file);
+      osm_log(p_log, OSM_LOG_SYS, 
+              "       Using general verbosity value.\n");
+      return;
+   }
+
+   p_log->table = st_init_strtable();
+   if (p_log->table == NULL)
+   {
+      osm_log(p_log, OSM_LOG_SYS, "ERROR: Verbosity table initialization failed.\n");
+      return;
+   }
+
+   /* 
+    * Read the file line by line, parse the lines, and
+    * add each line to p_log->table.
+    */
+   while ( fgets(line, sizeof(line), infile) != NULL )
+   {
+      char * str = line;
+      char * name = NULL;
+      char * value = NULL;
+      osm_log_level_t * p_log_level_value = NULL;
+      int res;
+
+      name = strtok_r(str," \t\n",&tmp_str);
+      if (name == NULL || strlen(name) == 0) {
+         /*
+          * empty line - ignore it
+          */
+         continue;
+      }
+      value = strtok_r(NULL," \t\n",&tmp_str);
+      if (value == NULL || strlen(value) == 0)
+      {
+         /*
+          * No verbosity value - wrong syntax.
+          * This line will be ignored.
+          */
+         continue;
+      }
+
+      /*
+       * If the conversion will fail, the log_level_value will get 0,
+       * so the only way to check that the syntax is correct is to
+       * scan value for any non-digit (which we're not doing here).
+       */
+      p_log_level_value = malloc (sizeof(osm_log_level_t));
+      if (!p_log_level_value)
+      {
+         osm_log(p_log, OSM_LOG_SYS, "ERROR: malloc failed.\n");
+         p_log->table = NULL;
+         fclose(infile);
+         return;
+      }
+      *p_log_level_value = strtoul(value, NULL, 0);
+
+      if (strcasecmp(name,OSM_VERBOSITY_ALL) == 0)
+      {
+         osm_log_set_level(p_log, *p_log_level_value);
+         free(p_log_level_value);
+      }
+      else
+      {
+         res = st_insert( p_log->table,
+                          (st_data_t) strdup(name),
+                          (st_data_t) p_log_level_value);
+         if (res != 0)
+         {
+            /* 
+             * Something is wrong with the verbosity table.
+             * We won't try to free the table, because there's 
+             * clearly something corrupted there.
+             */
+            osm_log(p_log, OSM_LOG_SYS, "ERROR: Failed adding verbosity table element.\n");
+            p_log->table = NULL;
+            fclose(infile);
+            return;
+         }
+         table_empty = FALSE;
+      }
+
+   }
+
+   if (table_empty)
+      __osm_log_free_verbosity_table(p_log);
+
+   fclose(infile);
+
+   __osm_log_print_verbosity_table(p_log);
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+static int
+__osm_log_print_verbosity_table_element(
+           IN st_data_t key,
+           IN st_data_t val,
+           IN st_data_t arg)
+{
+   osm_log( (osm_log_t* const) arg, 
+            OSM_LOG_INFO, 
+            "[verbosity] File: %s, Level: 0x%x\n",
+            (char *) key, *((osm_log_level_t *) val));
+   
+   return ST_CONTINUE;
+}
+
+static void
+__osm_log_print_verbosity_table(
+           IN osm_log_t* const p_log)
+{
+   osm_log( p_log, OSM_LOG_INFO, 
+            "[verbosity] Verbosity table loaded\n" );
+   osm_log( p_log, OSM_LOG_INFO, 
+            "[verbosity] General level: 0x%x\n",osm_log_get_level_ext(p_log,NULL));
+   
+   if (p_log->table) 
+   {
+      st_foreach( p_log->table,
+                  __osm_log_print_verbosity_table_element,
+                  (st_data_t) p_log );
+   }
+   osm_log_flush(p_log);
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+static int
+__osm_log_free_verbosity_table_element(
+           IN st_data_t key,
+           IN st_data_t val,
+           IN st_data_t arg)
+{
+   free( (char *) key );
+   free( (osm_log_level_t *) val );
+   return ST_DELETE;
+}
 
-    /* send it also to the log file */
+static void
+__osm_log_free_verbosity_table(
+           IN osm_log_t* p_log)
+{
+   if (!p_log->table)
+      return;
+
+   st_foreach( p_log->table,
+               __osm_log_free_verbosity_table_element,
+               (st_data_t) NULL);
+
+   st_free_table(p_log->table);
+   p_log->table = NULL;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+static inline const char *
+__osm_log_get_base_name(
+           IN const char * const p_filename)
+{
 #ifdef WIN32
-    GetLocalTime(&st);
-    fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
-                     st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
-                     pid, buffer);
+   char dir_separator = '\\';
 #else
-    fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s\n",
-             (result.tm_mon < 12 ? month_str[result.tm_mon] : "???"),
-             result.tm_mday, result.tm_hour,
-             result.tm_min, result.tm_sec,
-             usecs, pid, buffer);
-    fflush( p_log->out_port );
-#endif    
-  }
+   char dir_separator = '/';
+#endif
+   char * tmp_ptr;
+
+   if (!p_filename)
+      return NULL;
+
+   tmp_ptr = strrchr(p_filename,dir_separator);
+
+   if (!tmp_ptr)
+      return p_filename;
+   return tmp_ptr+1;
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+boolean_t
+osm_log_is_active_ext(
+           IN const osm_log_t* const p_log,
+           IN const char* const p_filename,
+           IN const osm_log_level_t level )
+{
+   osm_log_level_t tmp_lvl;
+   tmp_lvl = level & 
+             osm_log_get_level_ext(p_log,__osm_log_get_base_name(p_filename));
+   return ( tmp_lvl != 0 );
+}
+
+/***************************************************************************
+ ***************************************************************************/
+
+static int log_exit_count = 0;
+
+void
+osm_log_ext(
+           IN osm_log_t* const p_log,
+           IN const osm_log_level_t verbosity,
+           IN const char *p_filename,
+           IN int line,
+           IN const char *p_str, ... )
+{
+   char      buffer[LOG_ENTRY_SIZE_MAX];
+   va_list   args;
+   int       ret;
+   osm_log_level_t file_verbosity;
 
-  /* SYS messages go to the log anyways */
-  if (p_log->level & verbosity)
-  {
-    
-    va_start( args, p_str );
-    vsprintf( buffer, p_str, args );
-    va_end(args);
-    
-    /* regular log to default out_port */
-    cl_spinlock_acquire( &p_log->lock );
 #ifdef WIN32
-    GetLocalTime(&st);
- _retry:
-    ret = fprintf(   p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
-                     st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
-                     pid, buffer);
-    
+   SYSTEMTIME st;
+   uint32_t pid = GetCurrentThreadId();
 #else
-    pid = pthread_self();
-    tim = time(NULL);
- _retry:
-    ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
-                   ((result.tm_mon < 12) && (result.tm_mon >= 0) ? 
-                    month_str[result.tm_mon] : "???"),
-                   result.tm_mday, result.tm_hour,
-                   result.tm_min, result.tm_sec,
-                   usecs, pid, buffer);
-#endif /*  WIN32 */
+   pid_t pid = 0;
+   time_t tim;
+   struct tm result;
+   uint64_t time_usecs;
+   uint32_t usecs;
+
+   time_usecs = cl_get_time_stamp();
+   tim = time_usecs/1000000;
+   usecs = time_usecs % 1000000;
+   localtime_r(&tim, &result);
+#endif /* WIN32 */
+
+   /*
+    * Extract only the file name out of the full path
+    */
+   p_filename = __osm_log_get_base_name(p_filename);
+   /*
+    * Get the verbosity level for this file.
+    * If the file is not specified in the log config file,
+    * the general verbosity level will be returned.
+    */
+   file_verbosity = osm_log_get_level_ext(p_log, p_filename);
+
+   if ( ! (verbosity & OSM_LOG_SYS) &&
+        ! (file_verbosity & verbosity) )
+   {
+      /*
+       * This is not a syslog message (which is always printed)
+       * and doesn't have the required verbosity level.
+       */
+      return;
+   }
+
+   va_start( args, p_str );
+   vsprintf( buffer, p_str, args );
+   va_end(args);
+
+      
+   if ( verbosity & OSM_LOG_SYS )
+   {
+      /* this is a call to the syslog */
+      cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);
+      /* SYSLOG should go to stdout too */
+      if (p_log->out_port != stdout)
+      {
+         printf("%s", buffer);
+         fflush( stdout );
+      }
+   }
+   /* SYSLOG also goes to to the log file */
+
+   cl_spinlock_acquire( &p_log->lock );
 
-    if (ret >= 0)
+#ifdef WIN32
+   GetLocalTime(&st);
+_retry:
+   if (p_log->src_info) 
+   {
+      ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] [%s:%d] -> %s",
+                    st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+                    pid, p_filename, line, buffer);
+   }
+   else
+   {
+      ret = fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+                    st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
+                    pid, buffer);
+   }
+#else
+   pid = pthread_self();
+   tim = time(NULL);
+_retry:
+   if (p_log->src_info) 
+   {
+      ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] [%s:%d] -> %s",
+                     ((result.tm_mon < 12) && (result.tm_mon >= 0) ?
+                     month_str[result.tm_mon] : "???"),
+                     result.tm_mday, result.tm_hour,
+                     result.tm_min, result.tm_sec,
+                     usecs, pid, p_filename, line, buffer);
+   }
+   else
+   {
+      ret = fprintf( p_log->out_port, "%s %02d %02d:%02d:%02d %06d [%04X] -> %s",
+                     ((result.tm_mon < 12) && (result.tm_mon >= 0) ?
+                     month_str[result.tm_mon] : "???"),
+                     result.tm_mday, result.tm_hour,
+                     result.tm_min, result.tm_sec,
+                     usecs, pid, buffer);
+   }
+#endif
+
+   if (ret >= 0)
       log_exit_count = 0;
-    else if (errno == ENOSPC && log_exit_count < 3) {
+   else if (errno == ENOSPC && log_exit_count < 3) {
       int fd = fileno(p_log->out_port);
       fprintf(stderr, "osm_log write failed: %s. Truncating log file.\n",
               strerror(errno));
@@ -180,38 +547,58 @@ osm_log(
       lseek(fd, 0, SEEK_SET);
       log_exit_count++;
       goto _retry;
-    }
-    
-    /*
-      Flush log on errors too.
+   }
+
+   /*
+    * Flush log on errors and SYSLOGs too.
     */
-    if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+   if ( p_log->flush || 
+        (verbosity & OSM_LOG_ERROR) ||
+        (verbosity & OSM_LOG_SYS) )
       fflush( p_log->out_port );
-    
-    cl_spinlock_release( &p_log->lock );
-  }
+
+   cl_spinlock_release( &p_log->lock );
 }
 
+/***************************************************************************
+ ***************************************************************************/
+
 void
-osm_log_raw(
-  IN osm_log_t* const p_log,
-  IN const osm_log_level_t verbosity,
-  IN const char *p_buf )
+osm_log_raw_ext(
+           IN osm_log_t* const p_log,
+           IN const osm_log_level_t verbosity,
+           IN const char * p_filename,
+           IN const char *p_buf )
 {
-  if( p_log->level & verbosity )
-  {
-    cl_spinlock_acquire( &p_log->lock );
-    printf( "%s", p_buf );
-    cl_spinlock_release( &p_log->lock );
-
-    /*
-      Flush log on errors too.
+   osm_log_level_t file_verbosity;
+  /*
+   * Extract only the file name out of the full path
+   */
+   p_filename = __osm_log_get_base_name(p_filename);
+   /*
+    * Get the verbosity level for this file.
+    * If the file is not specified in the log config file,
+    * the general verbosity level will be returned.
     */
-    if( p_log->flush || (verbosity & OSM_LOG_ERROR) )
-      fflush( stdout );
-  }
+   file_verbosity = osm_log_get_level_ext(p_log, p_filename);
+
+   if ( file_verbosity & verbosity )
+   {
+      cl_spinlock_acquire( &p_log->lock );
+      printf( "%s", p_buf );
+      cl_spinlock_release( &p_log->lock );
+
+      /*
+        Flush log on errors too.
+      */
+      if ( p_log->flush || (verbosity & OSM_LOG_ERROR) )
+         fflush( stdout );
+   }
 }
 
+/***************************************************************************
+ ***************************************************************************/
+
 boolean_t
 osm_is_debug(void)
 {
@@ -221,3 +608,7 @@ osm_is_debug(void)
   return FALSE;
 #endif /* defined( _DEBUG_ ) */
 }
+
+/***************************************************************************
+ ***************************************************************************/
+
Index: opensm/main.c
===================================================================
--- opensm/main.c	(revision 9107)
+++ opensm/main.c	(working copy)
@@ -296,6 +296,33 @@ show_usage(void)
           "          -d3  - Disable multicast support\n"
           "          -d10 - Put OpenSM in testability mode\n"
           "          Without -d, no debug options are enabled\n\n" );
+  printf( "-S\n"
+          "--log_source_info\n"
+          "          This option tells SM to add source code filename\n"
+          "          and line number to every log message.\n"
+          "          By default, the SM will not log this additional info.\n\n");
+  printf( "-b\n"
+          "--verbosity_file <file name>\n"
+          "          This option specifies name of the verbosity\n"
+          "          configuration file, which describes verbosity level\n"
+          "          per source code file. The file may contain zero or\n"
+          "          more lines of the following pattern:\n"
+          "               filename verbosity_level\n"
+          "          where 'filename' is the name of the source code file\n" 
+          "          that the 'verbosity_level' refers to, and the \n"
+          "          'verbosity_level' itself should be specified as a\n"
+          "          number (decimal or hexadecimal).\n"
+          "          Filename 'all' represents general verbosity level,\n"
+          "          that is used for all the files that are not specified\n" 
+          "          in the verbosity file.\n"
+          "          Note: The 'all' file verbosity level will override any\n"
+          "          other general level that was specified by the command\n" 
+          "          line arguments.\n"
+          "          By default, the SM will use the following file:\n"
+          "             %s\n"
+          "          Sending a SIGHUP signal to the SM will cause it to\n"
+          "          re-read the verbosity configuration file.\n"
+          "\n\n", OSM_DEFAULT_VERBOSITY_FILE);
   printf( "-h\n"
           "--help\n"
           "          Display this usage info then exit.\n\n" );
@@ -527,7 +554,7 @@ main(
   boolean_t             cache_options = FALSE;
   char                 *ignore_guids_file_name = NULL;
   uint32_t              val;
-  const char * const    short_option = "i:f:ed:g:l:s:t:a:R:U:P:NQvVhorcyx";
+  const char * const    short_option = "i:f:ed:g:l:s:t:a:R:U:P:b:SNQvVhorcyx";
 
   /*
     In the array below, the 2nd parameter specified the number
@@ -564,7 +591,9 @@ main(
       {  "add_guid_file", 1, NULL, 'a'},
       {  "cache-options", 0, NULL, 'c'},
       {  "stay_on_fatal", 0, NULL, 'y'},
-      {  "honor_guid2lid", 0, NULL, 'x'},
+      {  "honor_guid2lid",0, NULL, 'x'},
+      {  "log_source_info",0,NULL, 'S'},
+      {  "verbosity_file",1, NULL, 'b'},
       {  NULL,            0, NULL,  0 }  /* Required at the end of the array */
     };
 
@@ -808,6 +837,16 @@ main(
       printf (" Honor guid2lid file, if possible\n");
       break;
 
+    case 'S':
+      opt.src_info = TRUE;
+      printf(" Logging source code filename and line number\n");
+      break;
+
+    case 'b':
+      opt.verbosity_file = optarg;
+      printf(" Verbosity Configuration File: %s\n", optarg);
+      break;
+
     case 'h':
     case '?':
     case ':':
@@ -920,9 +959,13 @@ main(
 
       if (osm_hup_flag) {
         osm_hup_flag = 0;
-        /* a HUP signal should only start a new heavy sweep */
+        /* 
+         * A HUP signal should cause OSM to re-read the log
+         * configuration file and start a new heavy sweep 
+         */
         osm.subn.force_immediate_heavy_sweep = TRUE;
         osm_opensm_sweep( &osm );
+        osm_log_read_verbosity_file(&osm.log,opt.verbosity_file);
       }
     }
   }
Index: opensm/Makefile.am
===================================================================
--- opensm/Makefile.am	(revision 9107)
+++ opensm/Makefile.am	(working copy)
@@ -43,7 +43,7 @@ else
 libopensm_version_script =
 endif
 
-libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c
+libopensm_la_SOURCES = osm_log.c osm_mad_pool.c osm_helper.c st.c
 libopensm_la_LDFLAGS = -version-info $(opensm_api_version) \
 	-export-dynamic $(libopensm_version_script)
 libopensm_la_DEPENDENCIES = $(srcdir)/libopensm.map
@@ -90,7 +90,7 @@ opensm_SOURCES = main.c osm_console.c os
 		 osm_trap_rcv.c osm_trap_rcv_ctrl.c \
 		 osm_ucast_mgr.c osm_ucast_updn.c osm_ucast_file.c \
 		 osm_vl15intf.c osm_vl_arb_rcv.c \
-		 osm_vl_arb_rcv_ctrl.c st.c
+		 osm_vl_arb_rcv_ctrl.c
 if OSMV_OPENIB
 opensm_CFLAGS = -Wall $(OSMV_CFLAGS) -fno-strict-aliasing -DVENDOR_RMPP_SUPPORT -DDUAL_SIDED_RMPP $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
 opensm_CXXFLAGS = -Wall $(OSMV_CFLAGS) -DVENDOR_RMPP_SUPPORT -DDUAL_SIDED_RMPP $(DBGFLAGS) -D_XOPEN_SOURCE=600 -D_BSD_SOURCE=1
Index: doc/verbosity-config.txt
===================================================================
--- doc/verbosity-config.txt	(revision 0)
+++ doc/verbosity-config.txt	(revision 0)
@@ -0,0 +1,43 @@
+
+This patch adds new verbosity functionality.
+
+1. Verbosity configuration file
+-------------------------------
+
+The user is able to set verbosity level per source code file
+by supplying verbosity configuration file using the following
+command line arguments:
+
+      -b filename 
+      --verbosity_file filename
+
+By default, the OSM will use the following file: /etc/osm-log.conf
+Verbosity configuration file should contain zero or more lines of 
+the following pattern:
+
+      filename verbosity_level
+
+where 'filename' is the name of the source code file that the 
+'verbosity_level' refers to, and the 'verbosity_level' itself 
+should be specified as an integer number (decimal or hexadecimal).
+
+One reserved filename is 'all' - it represents general verbosity 
+level, that is used for all the files that are not specified in
+the verbosity configuration file.
+If 'all' is not specified, the verbosity level set in the
+command line will be used instead. 
+Note: The 'all' file verbosity level will override any other 
+general level that was specified by the command line arguments.
+
+Sending a SIGHUP signal to the OSM will cause it to reload
+the verbosity configuration file.
+
+
+2. Logging source code filename and line number
+-----------------------------------------------
+
+If command line option -S or --log_source_info is specified,
+OSM will add source code filename and line number to every 
+log message that is written to the log file.
+By default, the OSM will not log this additional info.
+ 
Index: man/opensm.8
===================================================================
--- man/opensm.8        (revision 9107)
+++ man/opensm.8        (working copy)
@@ -5,7 +5,7 @@ opensm \- InfiniBand subnet manager and

 .SH SYNOPSIS
 .B opensm
-[\-c(ache_options)] [\-g(uid)[=]<GUID in hex>] [\-l(mc) <LMC>] [\-p(riority) <PRIORITY>] [\-smkey <SM_Key>] [\-r(eassign_lids)] [\-R <engine name> | \-routing_engine <engine name>] [\-U <file name> | \-ucast_file <file name>] [\-a(dd_guid_file) <path to file>] [\-o(nce)] [\-s(weep) <interval>] [\-t(imeout) <milliseconds>] [\-maxsmps <number>] [\-console] [\-i(gnore-guids) <equalize-ignore-guids-file>] [\-f | \-\-log_file] [\-e(rase_log_file)] [\-P(config)] [\-Q | \-no_qos] [\-N | \-no_part_enforce] [\-y | \-stay_on_fatal] [\-v(erbose)] [\-V] [\-D <flags>] [\-d(ebug) <number>] [\-h(elp)] [\-?]
+[\-c(ache_options)] [\-g(uid)[=]<GUID in hex>] [\-l(mc) <LMC>] [\-p(riority) <PRIORITY>] [\-smkey <SM_Key>] [\-r(eassign_lids)] [\-R <engine name> | \-routing_engine <engine name>] [\-U <file name> | \-ucast_file <file name>] [\-a(dd_guid_file) <path to file>] [\-o(nce)] [\-s(weep) <interval>] [\-t(imeout) <milliseconds>] [\-maxsmps <number>] [\-console] [\-i(gnore-guids) <equalize-ignore-guids-file>] [\-f | \-\-log_file] [\-e(rase_log_file)] [\-P(config)] [\-Q | \-no_qos] [\-N | \-no_part_enforce] [\-y | \-stay_on_fatal] [\-v(erbose)] [\-V] [\-D <flags>] [\-d(ebug) <number>] [\-S | \-log_source_info] [\-b <file name> | \-verbosity_file <file name>] [\-h(elp)] [\-?]

 .SH DESCRIPTION
 .PP
@@ -208,6 +208,33 @@ option to enable as follows:
  -d2  - Force log flushing after each log message
  -d3  - Disable multicast support
 .TP
+\fB\-S\fR, \fB\-\-log_source_info\fR
+This option tells SM to add source code filename
+and line number to every log message.
+By default, the SM will not log this additional info.
+.TP
+\fB\-b\fR, \fB\-\-verbosity_file\fR
+This option specifies name of the verbosity
+configuration file, which describes verbosity level
+per source code file.
+By default, the SM will use /etc/osm-log.conf.
+The file may contain zero or more lines of the
+following pattern:
+
+  filename verbosity_level
+
+where 'filename' is the name of the source code file
+that the 'verbosity_level' refers to, and the 'verbosity_level'
+itself should be specified as a number (decimal or hexadecimal).
+Filename 'all' represents general verbosity level,
+that is used for all the files that are not specified
+in the verbosity file.
+Note: The 'all' file verbosity level will override any
+other general level that was specified by the command
+line arguments.
+Sending a SIGHUP signal to the SM will cause it to
+re-read the verbosity configuration file.
+.TP
 \fB\-h\fR, \fB\-\-help\fR
 Display this usage info then exit.
 .TP





More information about the general mailing list