2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_log_t.
39 * This object represents the log file.
40 * This object is part of the opensm family of objects.
45 #endif /* HAVE_CONFIG_H */
47 #include <opensm/osm_log.h>
52 #include <sys/types.h>
56 static int log_exit_count = 0;
61 #include <complib/cl_timer.h>
63 static char *month_str[] = {
78 void OsmReportState(IN const char *p_str);
79 #endif /* ndef WIN32 */
83 static void truncate_log_file(osm_log_t * const p_log)
85 int fd = fileno(p_log->out_port);
86 if (ftruncate(fd, 0) < 0)
87 fprintf(stderr, "truncate_log_file: cannot truncate: %s\n",
89 if (lseek(fd, 0, SEEK_SET) < 0)
90 fprintf(stderr, "truncate_log_file: cannot rewind: %s\n",
97 static void truncate_log_file(osm_log_t * const p_log)
100 "truncate_log_file: cannot truncate on windows system (yet)\n");
102 #endif /* ndef WIN32 */
104 void osm_log(IN osm_log_t * const p_log,
105 IN const osm_log_level_t verbosity, IN const char *p_str, ...)
107 char buffer[LOG_ENTRY_SIZE_MAX];
112 uint32_t pid = GetCurrentThreadId();
121 /* If this is a call to syslog - always print it */
122 if (!(verbosity & (OSM_LOG_SYS | p_log->level)))
125 va_start(args, p_str);
126 vsprintf(buffer, p_str, args);
129 /* this is a call to the syslog */
130 if (verbosity & OSM_LOG_SYS) {
131 syslog(LOG_INFO, "%s\n", buffer);
133 /* SYSLOG should go to stdout too */
134 if (p_log->out_port != stdout) {
135 printf("%s\n", buffer);
139 OsmReportState(buffer);
143 /* regular log to default out_port */
144 cl_spinlock_acquire(&p_log->lock);
146 if (p_log->max_size && p_log->count > p_log->max_size) {
149 "osm_log: log file exceeds the limit %lu. Truncating.\n",
151 truncate_log_file(p_log);
157 fprintf(p_log->out_port,
158 "[%02d:%02d:%02d:%03d][%04X] 0x%02x -> %s",
159 st.wHour, st.wMinute, st.wSecond, st.wMilliseconds,
160 pid, verbosity, buffer);
162 time_usecs = cl_get_time_stamp();
163 tim = time_usecs / 1000000;
164 usecs = time_usecs % 1000000;
165 localtime_r(&tim, &result);
166 pid = pthread_self();
169 fprintf(p_log->out_port,
170 "%s %02d %02d:%02d:%02d %06d [%04X] 0x%02x -> %s",
172 12 ? month_str[result.tm_mon] : "???"),
173 result.tm_mday, result.tm_hour, result.tm_min,
174 result.tm_sec, usecs, pid, verbosity, buffer);
179 (p_log->flush || (verbosity & (OSM_LOG_ERROR | OSM_LOG_SYS)))
180 && fflush(p_log->out_port) < 0)
186 } else if (log_exit_count < 3) {
188 if (errno == ENOSPC && p_log->max_size) {
190 "osm_log: write failed: %s. Truncating log file.\n",
192 truncate_log_file(p_log);
195 fprintf(stderr, "osm_log: write failed: %s\n", strerror(errno));
198 cl_spinlock_release(&p_log->lock);
201 void osm_log_raw(IN osm_log_t * const p_log,
202 IN const osm_log_level_t verbosity, IN const char *p_buf)
204 if (p_log->level & verbosity) {
205 cl_spinlock_acquire(&p_log->lock);
207 cl_spinlock_release(&p_log->lock);
210 Flush log on errors too.
212 if (p_log->flush || (verbosity & OSM_LOG_ERROR))
217 void osm_log_msg_box(IN osm_log_t * log, osm_log_level_t level,
218 const char *func_name, const char *msg)
220 #define MSG_BOX_LENGTH 66
221 char buf[MSG_BOX_LENGTH + 1];
224 if (!osm_log_is_active(log, level))
227 n = (MSG_BOX_LENGTH - strlen(msg)) / 2 - 1;
230 for (i = 0; i < n; i++)
231 sprintf(buf + i, "*");
232 n += snprintf(buf + n, sizeof(buf) - n, " %s ", msg);
233 for (i = n; i < MSG_BOX_LENGTH; i++)
237 osm_log(log, level, "%s:\n\n\n"
238 "*********************************************"
239 "*********************\n%s\n"
240 "*********************************************"
241 "*********************\n\n\n", func_name, buf);
244 boolean_t osm_is_debug(void)
246 #if defined( _DEBUG_ )
250 #endif /* defined( _DEBUG_ ) */
253 static int open_out_port(IN osm_log_t * p_log)
257 if (p_log->accum_log_file)
258 p_log->out_port = fopen(p_log->log_file_name, "a+");
260 p_log->out_port = fopen(p_log->log_file_name, "w+");
262 if (!p_log->out_port) {
263 syslog(LOG_CRIT, "Cannot open file \'%s\' for %s: %s\n",
264 p_log->log_file_name,
265 p_log->accum_log_file ? "appending" : "writing",
267 fprintf(stderr, "Cannot open file \'%s\': %s\n",
268 p_log->log_file_name, strerror(errno));
272 if (fstat(fileno(p_log->out_port), &st) == 0)
273 p_log->count = st.st_size;
275 syslog(LOG_NOTICE, "%s log file opened\n", p_log->log_file_name);
278 dup2(fileno(p_log->out_port), 0);
279 dup2(fileno(p_log->out_port), 1);
280 dup2(fileno(p_log->out_port), 2);
286 int osm_log_reopen_file(osm_log_t * p_log)
290 if (p_log->out_port == stdout || p_log->out_port == stderr)
292 cl_spinlock_acquire(&p_log->lock);
293 fclose(p_log->out_port);
294 ret = open_out_port(p_log);
295 cl_spinlock_release(&p_log->lock);
299 ib_api_status_t osm_log_init_v2(IN osm_log_t * const p_log,
300 IN const boolean_t flush,
301 IN const uint8_t log_flags,
302 IN const char *log_file,
303 IN const unsigned long max_size,
304 IN const boolean_t accum_log_file)
306 p_log->level = log_flags;
307 p_log->flush = flush;
309 p_log->max_size = max_size;
310 p_log->accum_log_file = accum_log_file;
311 p_log->log_file_name = (char *)log_file;
313 openlog("OpenSM", LOG_CONS | LOG_PID, LOG_USER);
315 if (log_file == NULL || !strcmp(log_file, "-") ||
316 !strcmp(log_file, "stdout"))
317 p_log->out_port = stdout;
318 else if (!strcmp(log_file, "stderr"))
319 p_log->out_port = stderr;
320 else if (open_out_port(p_log))
323 if (cl_spinlock_init(&p_log->lock) == CL_SUCCESS)
329 ib_api_status_t osm_log_init(IN osm_log_t * const p_log,
330 IN const boolean_t flush,
331 IN const uint8_t log_flags,
332 IN const char *log_file,
333 IN const boolean_t accum_log_file)
335 return osm_log_init_v2(p_log, flush, log_flags, log_file, 0,