[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