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

Yevgeny Kliteynik kliteyn at gmail.com
Wed Aug 2 08:16:32 PDT 2006


Hi Hal

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/opensmlog.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.


Yevgeny

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

Index: include/opensm/osm_subnet.h
===================================================================
--- include/opensm/osm_subnet.h    (revision 8614)
+++ 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 8614)
+++ 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(), "opensmlog.conf")
+#else
+#define OSM_DEFAULT_VERBOSITY_FILE "/etc/opensmlog.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 8652)
+++ 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,26 +299,32 @@ 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 8614)
+++ 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 8614)
+++ 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 8614)
+++ opensm/libopensm.map    (working copy)
@@ -1,6 +1,11 @@
-OPENSM_1.0 {
+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.0 {
         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.0 {
         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 8614)
+++ opensm/osm_log.c    (working copy)
@@ -80,17 +80,365 @@ static char *month_str[] = {
 };
 #endif /* ndef 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;
+}
+
+/***************************************************************************
+
***************************************************************************/
+
+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
+  {
+    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_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;
+}
+
+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
+   char dir_separator = '\\';
+#else
+   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(
+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;

 #ifdef WIN32
   SYSTEMTIME st;
@@ -108,69 +456,89 @@ osm_log(
   localtime_r(&tim, &result);
 #endif /* WIN32 */

-  /* If this is a call to syslog - always print it */
-  if ( verbosity & OSM_LOG_SYS )
+   /*
+    * 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 a call to the syslog */
+      /*
+       * 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);
-    cl_log_event("OpenSM", LOG_INFO, buffer , NULL, 0);

+
+   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\n", buffer);
+         printf("%s", buffer);
       fflush( stdout );
     }
+   }
+   /* SYSLOG also goes to to the log file */
+
+   cl_spinlock_acquire( &p_log->lock );

-    /* send it also to the log file */
 #ifdef WIN32
     GetLocalTime(&st);
-    fprintf( p_log->out_port, "[%02d:%02d:%02d:%03d][%04X] -> %s",
+   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, buffer);
-#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
+                    pid, p_filename, line, buffer);
   }
-
-  /* SYS messages go to the log anyways */
-  if (p_log->level & verbosity)
+   else
   {
-
-    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);
     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);
+   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 /*  WIN32 */
-
+   }
+#endif
     /*
-      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 );
@@ -183,15 +551,30 @@ osm_log(
       }
     }
   }
-}
+
+/***************************************************************************
+
***************************************************************************/

 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 )
 {
-  if( p_log->level & verbosity )
+   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.
+    */
+   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 );
@@ -205,6 +588,9 @@ osm_log_raw(
   }
 }

+/***************************************************************************
+
***************************************************************************/
+
 boolean_t
 osm_is_debug(void)
 {
@@ -214,3 +600,7 @@ osm_is_debug(void)
   return FALSE;
 #endif /* defined( _DEBUG_ ) */
 }
+
+/***************************************************************************
+
***************************************************************************/
+
Index: opensm/main.c
===================================================================
--- opensm/main.c    (revision 8652)
+++ 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
@@ -565,6 +592,8 @@ main(
       {  "cache-options", 0, NULL, 'c'},
       {  "stay_on_fatal", 0, NULL, 'y'},
       {  "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 8614)
+++ 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/opensmlog.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.
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openfabrics.org/pipermail/general/attachments/20060802/6a369e0b/attachment.html>


More information about the general mailing list