Files
scst/iscsi-scst/usr/log.c
Vladislav Bolkhovitin 7a87bf25a6 Cleanup + implement conditional logging
This patch:
* fixes signatures for log_debug and log_pdu macros
* collapses __log_<LEVEL> functions into one
* adds conditional logging

Here conditional logging means that the logging priority and logging level may
vary depending on some dynamic parameters. This is helpful when software is
able to recover from errors which occur periodically and hence, there is no
need to pollute system logs with tons of repetitive non-critical lines.

The following macros are added to support this feature:
* log_info_cond
* log_warning_cond
* log_error_cond

They take an additional first parameter called "level". If it is 0 then they
act as their non-cond counterparts, otherwise they act like log_debug with the
specified level.

Those who are not interested in conditional logging are not affected: they can
continue using plain old logging macros without any changes.

Signed-off-by: Sergey Myasnikov <tigra564@gmail.com>



git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@4161 d57e44dd-8a1f-0410-8b47-8ef2f437770f
2012-03-12 22:31:13 +00:00

172 lines
4.0 KiB
C

/*
* Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
* Copyright (C) 2007 - 2011 Vladislav Bolkhovitin
* Copyright (C) 2007 - 2010 ID7 Ltd.
* Copyright (C) 2010 - 2011 SCST Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <syslog.h>
#include <sys/time.h>
#include <string.h>
#include "iscsid.h"
int log_daemon = 1;
int log_level = 0;
void log_init(void)
{
if (log_daemon)
openlog("iscsi-scstd", 0, LOG_DAEMON);
}
static void dolog_nofunc(int prio, const char *fmt, va_list ap)
{
if (log_daemon) {
int len = strlen(fmt);
char f[len+1+1];
if (fmt[len] != '\n')
sprintf(f, "%s\n", fmt);
else
sprintf(f, "%s", fmt);
vsyslog(prio, f, ap);
} else {
struct timeval time;
gettimeofday(&time, NULL);
fprintf(stderr, "%ld.%06ld: ", time.tv_sec, time.tv_usec);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
fflush(stderr);
}
}
static void dolog(int prio, const char *func, int line, const char *fmt, va_list ap)
{
if (log_level == 0) {
dolog_nofunc(prio, fmt, ap);
return;
}
if (log_daemon) {
int len = strlen(func) + strlen(fmt);
char f[len+1+1];
if (fmt[len] != '\n')
sprintf(f, "%s:%d: %s %s\n", func, line,
(prio == LOG_ERR) ? "ERROR:" : "", fmt);
else
sprintf(f, "%s:%d: %s %s", func, line,
(prio == LOG_ERR) ? "ERROR: " : "", fmt);
vsyslog(prio, f, ap);
} else {
struct timeval time;
gettimeofday(&time, NULL);
fprintf(stderr, "%ld.%06ld: %s:%d: ", time.tv_sec, time.tv_usec, func, line);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
fflush(stderr);
}
}
void __log(const char *func, int line, int prio, int level, const char *fmt, ...)
{
if (level) {
prio = LOG_DEBUG;
if (log_level < level)
return;
}
va_list ap;
va_start(ap, fmt);
dolog(prio, func, line, fmt, ap);
va_end(ap);
}
/* Definition for __log_pdu buffer */
#define BUFFER_SIZE 16
/*
* size required for a hex dump of BUFFER_SIZE bytes (' ' + 2 chars = 3 chars
* per byte) with a ' |' separator each 4th byte:
*/
#define LINE_SIZE (BUFFER_SIZE * 3 + BUFFER_SIZE / 4 * 2 + 1)
static void __dump_line(const char *func, int line_num, int level, unsigned char *buf, int *cp)
{
char line[LINE_SIZE], *lp = line;
int i, cnt;
cnt = *cp;
if (!cnt)
return;
for (i = 0; i < BUFFER_SIZE; i++) {
if (i < cnt)
lp += sprintf(lp, " %02x", buf[i]);
else
lp += sprintf(lp, " ");
if ((i % 4) == 3)
lp += sprintf(lp, " |");
if (i >= cnt || !isprint(buf[i]))
buf[i] = ' ';
}
/* buf is not \0-terminated! */
__log(func, line_num, LOG_DEBUG, level, "%s %.*s |", line, BUFFER_SIZE, buf);
*cp = 0;
}
static void __dump_char(const char *func, int line, int level, unsigned char *buf, int *cp, int ch)
{
int cnt = (*cp)++;
buf[cnt] = ch;
if (cnt == BUFFER_SIZE - 1)
__dump_line(func, line, level, buf, cp);
}
#define dump_line() __dump_line(func, line, level, char_buf, &char_cnt)
#define dump_char(ch) __dump_char(func, line, level, char_buf, &char_cnt, ch)
void __log_pdu(const char *func, int line, int level, struct PDU *pdu)
{
unsigned char char_buf[BUFFER_SIZE];
int char_cnt = 0;
unsigned char *buf;
int i;
if (log_level < level)
return;
buf = (void *)&pdu->bhs;
__log(func, line, LOG_DEBUG, level, "BHS: (%p)", buf);
for (i = 0; i < BHS_SIZE; i++)
dump_char(*buf++);
dump_line();
buf = (void *)pdu->ahs;
__log(func, line, LOG_DEBUG, level, "AHS: (%p)", buf);
for (i = 0; i < pdu->ahssize; i++)
dump_char(*buf++);
dump_line();
buf = (void *)pdu->data;
__log(func, line, LOG_DEBUG, level, "Data: (%p)", buf);
for (i = 0; i < pdu->datasize; i++)
dump_char(*buf++);
dump_line();
}