summaryrefslogtreecommitdiffstats
path: root/lib/log.c
diff options
context:
space:
mode:
authorChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-02 17:11:35 +0000
committerChris Hall (GMCH) <chris.hall@highwayman.com>2009-12-02 17:11:35 +0000
commit8364e12dd2737cf77a4e3ead7c3d7bb9cc684010 (patch)
treebbcf4243478504ad6d5c6c9183ba7a81a8118b7a /lib/log.c
parentdb597018b8c47208e4139b75fdcd798505695ea8 (diff)
parent1e2ad204c4c72cb3ffa73864154c96047da8cad4 (diff)
downloadquagga-8364e12dd2737cf77a4e3ead7c3d7bb9cc684010.tar.bz2
quagga-8364e12dd2737cf77a4e3ead7c3d7bb9cc684010.tar.xz
Merge branch 'pthreads' of /git/quagga.euro-ix into pthreads
Diffstat (limited to 'lib/log.c')
-rw-r--r--lib/log.c553
1 files changed, 455 insertions, 98 deletions
diff --git a/lib/log.c b/lib/log.c
index 0c2f655b..ab8bd47e 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -34,6 +34,26 @@
#ifdef HAVE_UCONTEXT_H
#include <ucontext.h>
#endif
+#include <pthread.h>
+#include <assert.h>
+
+/* logging needs to be pthread safe */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#if 0
+static int lock_count = 0;
+#define LOCK if(lock_count++ != 0){printf("Lock count: %d\n", lock_count);assert(0);}
+#define UNLOCK if(--lock_count != 0){printf("Unlock count: %d\n", lock_count);assert(0);}
+#elif defined(NDEBUG)
+#define LOCK pthread_mutex_lock(&mutex);
+#define UNLOCK pthread_mutex_unlock(&mutex);
+#else
+#define LOCK if(pthread_mutex_lock(&mutex)!= 0){assert(0);};
+#define UNLOCK if(pthread_mutex_unlock(&mutex)!= 0){assert(0);};
+#endif
+
+/* prototypes */
+static int do_reset_file (struct zlog *zl);
+static size_t do_timestamp(int timestamp_precision, char *buf, size_t buflen);
static int logfile_fd = -1; /* Used in signal handler. */
@@ -74,6 +94,16 @@ const char *zlog_priority[] =
size_t
quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
{
+ size_t result;
+ LOCK
+ result = do_timestamp(timestamp_precision, buf, buflen);
+ UNLOCK
+ return result;
+}
+
+static size_t
+do_timestamp(int timestamp_precision, char *buf, size_t buflen)
+{
static struct {
time_t last;
size_t len;
@@ -81,6 +111,8 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
} cache;
struct timeval clock;
+ size_t result = 0;
+
/* would it be sufficient to use global 'recent_time' here? I fear not... */
gettimeofday(&clock, NULL);
@@ -122,14 +154,19 @@ quagga_timestamp(int timestamp_precision, char *buf, size_t buflen)
}
while (--prec > 0);
*p = '.';
- return cache.len+1+timestamp_precision;
+ result = cache.len+1+timestamp_precision;
}
- buf[cache.len] = '\0';
- return cache.len;
+ else
+ {
+ buf[cache.len] = '\0';
+ result = cache.len;
+ }
+ } else {
+ if (buflen > 0)
+ buf[0] = '\0';
}
- if (buflen > 0)
- buf[0] = '\0';
- return 0;
+
+ return result;
}
/* Utility routine for current time printing. */
@@ -138,7 +175,7 @@ time_print(FILE *fp, struct timestamp_control *ctl)
{
if (!ctl->already_rendered)
{
- ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf));
+ ctl->len = do_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf));
ctl->already_rendered = 1;
}
fprintf(fp, "%s ", ctl->buf);
@@ -152,6 +189,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args)
struct timestamp_control tsctl;
tsctl.already_rendered = 0;
+ LOCK
+
/* If zlog is not specified, use default one. */
if (zl == NULL)
zl = zlog_default;
@@ -165,55 +204,65 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args)
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
fflush (stderr);
-
- /* In this case we return at here. */
- return;
}
- tsctl.precision = zl->timestamp_precision;
-
- /* Syslog output */
- if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
+ else
{
- va_list ac;
- va_copy(ac, args);
- vsyslog (priority|zlog_default->facility, format, ac);
- va_end(ac);
- }
+ tsctl.precision = zl->timestamp_precision;
- /* File output. */
- if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
- {
- va_list ac;
- time_print (zl->fp, &tsctl);
- if (zl->record_priority)
- fprintf (zl->fp, "%s: ", zlog_priority[priority]);
- fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
- va_copy(ac, args);
- vfprintf (zl->fp, format, ac);
- va_end(ac);
- fprintf (zl->fp, "\n");
- fflush (zl->fp);
- }
+ /* Syslog output */
+ if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG])
+ {
+ va_list ac;
+ va_copy(ac, args);
+ vsyslog (priority|zlog_default->facility, format, ac);
+ va_end(ac);
+ }
- /* stdout output. */
- if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
- {
- va_list ac;
- time_print (stdout, &tsctl);
- if (zl->record_priority)
- fprintf (stdout, "%s: ", zlog_priority[priority]);
- fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
- va_copy(ac, args);
- vfprintf (stdout, format, ac);
- va_end(ac);
- fprintf (stdout, "\n");
- fflush (stdout);
- }
+ /* File output. */
+ if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp)
+ {
+ va_list ac;
+ time_print (zl->fp, &tsctl);
+ if (zl->record_priority)
+ fprintf (zl->fp, "%s: ", zlog_priority[priority]);
+ fprintf (zl->fp, "%s: ", zlog_proto_names[zl->protocol]);
+ va_copy(ac, args);
+ vfprintf (zl->fp, format, ac);
+ va_end(ac);
+ fprintf (zl->fp, "\n");
+ fflush (zl->fp);
+ }
- /* Terminal monitor. */
- if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
- vty_log ((zl->record_priority ? zlog_priority[priority] : NULL),
- zlog_proto_names[zl->protocol], format, &tsctl, args);
+ /* stdout output. */
+ if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT])
+ {
+ va_list ac;
+ time_print (stdout, &tsctl);
+ if (zl->record_priority)
+ fprintf (stdout, "%s: ", zlog_priority[priority]);
+ fprintf (stdout, "%s: ", zlog_proto_names[zl->protocol]);
+ va_copy(ac, args);
+ vfprintf (stdout, format, ac);
+ va_end(ac);
+ fprintf (stdout, "\n");
+ fflush (stdout);
+ }
+
+ /* Terminal monitor. */
+ if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR])
+ {
+ /* must be unlocked as vty handles it's own pthread stuff
+ * extract what we need from the zlog first
+ */
+ const char *priority_name = (zl->record_priority ? zlog_priority[priority] : NULL);
+ const char *proto_name = zlog_proto_names[zl->protocol];
+
+ UNLOCK
+ vty_log (priority_name, proto_name, format, &tsctl, args);
+ return;
+ }
+ }
+ UNLOCK
}
static char *
@@ -608,12 +657,16 @@ _zlog_assert_failed (const char *assertion, const char *file,
unsigned int line, const char *function)
{
/* Force fallback file logging? */
+ LOCK
if (zlog_default && !zlog_default->fp &&
((logfile_fd = open_crashlog()) >= 0) &&
((zlog_default->fp = fdopen(logfile_fd, "w")) != NULL))
zlog_default->maxlvl[ZLOG_DEST_FILE] = LOG_ERR;
+ UNLOCK
+
zlog(NULL, LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
assertion,file,line,(function ? function : "?"));
+
zlog_backtrace(LOG_CRIT);
abort();
}
@@ -648,22 +701,33 @@ openzlog (const char *progname, zlog_proto_t protocol,
void
closezlog (struct zlog *zl)
{
+ LOCK
+
closelog();
if (zl->fp != NULL)
fclose (zl->fp);
XFREE (MTYPE_ZLOG, zl);
+
+ UNLOCK
}
/* Called from command.c. */
void
zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level)
{
+ LOCK
+
if (zl == NULL)
zl = zlog_default;
- zl->maxlvl[dest] = log_level;
+ if (zl != NULL)
+ {
+ zl->maxlvl[dest] = log_level;
+ }
+
+ UNLOCK
}
int
@@ -671,46 +735,68 @@ zlog_set_file (struct zlog *zl, const char *filename, int log_level)
{
FILE *fp;
mode_t oldumask;
+ int result = 1;
+
+ LOCK
/* There is opend file. */
- zlog_reset_file (zl);
+ do_reset_file (zl);
/* Set default zl. */
if (zl == NULL)
zl = zlog_default;
- /* Open file. */
- oldumask = umask (0777 & ~LOGFILE_MASK);
- fp = fopen (filename, "a");
- umask(oldumask);
- if (fp == NULL)
- return 0;
-
- /* Set flags. */
- zl->filename = strdup (filename);
- zl->maxlvl[ZLOG_DEST_FILE] = log_level;
- zl->fp = fp;
- logfile_fd = fileno(fp);
+ if (zl != NULL)
+ {
+ /* Open file. */
+ oldumask = umask (0777 & ~LOGFILE_MASK);
+ fp = fopen (filename, "a");
+ umask(oldumask);
+ if (fp == NULL)
+ result = 0;
+ else
+ {
+ /* Set flags. */
+ zl->filename = strdup (filename);
+ zl->maxlvl[ZLOG_DEST_FILE] = log_level;
+ zl->fp = fp;
+ logfile_fd = fileno(fp);
+ }
+ }
- return 1;
+ UNLOCK
+ return result;
}
/* Reset opend file. */
int
zlog_reset_file (struct zlog *zl)
{
+ int result;
+ LOCK
+ result = do_reset_file(zl);
+ UNLOCK
+ return result;
+}
+
+static int
+do_reset_file (struct zlog *zl)
+ {
if (zl == NULL)
zl = zlog_default;
- if (zl->fp)
- fclose (zl->fp);
- zl->fp = NULL;
- logfile_fd = -1;
- zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
-
- if (zl->filename)
- free (zl->filename);
- zl->filename = NULL;
+ if (zl != NULL)
+ {
+ if (zl->fp)
+ fclose (zl->fp);
+ zl->fp = NULL;
+ logfile_fd = -1;
+ zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+
+ if (zl->filename)
+ free (zl->filename);
+ zl->filename = NULL;
+ }
return 1;
}
@@ -721,38 +807,309 @@ zlog_rotate (struct zlog *zl)
{
int level;
+ LOCK
+
if (zl == NULL)
zl = zlog_default;
- if (zl->fp)
- fclose (zl->fp);
- zl->fp = NULL;
- logfile_fd = -1;
- level = zl->maxlvl[ZLOG_DEST_FILE];
- zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+ if (zl != NULL)
+ {
+ if (zl->fp)
+ fclose (zl->fp);
+ zl->fp = NULL;
+ logfile_fd = -1;
+ level = zl->maxlvl[ZLOG_DEST_FILE];
+ zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
+
+ if (zl->filename)
+ {
+ mode_t oldumask;
+ int save_errno;
+
+ oldumask = umask (0777 & ~LOGFILE_MASK);
+ zl->fp = fopen (zl->filename, "a");
+ save_errno = errno;
+ umask(oldumask);
+ if (zl->fp == NULL)
+ {
+ /* can't call logging while locked */
+ char *fname = strdup(zl->filename);
+ UNLOCK
+ zlog_err("Log rotate failed: cannot open file %s for append: %s",
+ fname, safe_strerror(save_errno));
+ free(fname);
+ return -1;
+ }
+ else
+ {
+ logfile_fd = fileno(zl->fp);
+ zl->maxlvl[ZLOG_DEST_FILE] = level;
+ }
+ }
+ }
+ UNLOCK
+ return 1;
+}
+
+int
+zlog_get_default_lvl (struct zlog *zl)
+{
+ int result = LOG_DEBUG;
- if (zl->filename)
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
{
- mode_t oldumask;
- int save_errno;
+ result = zl->default_lvl;
+ }
- oldumask = umask (0777 & ~LOGFILE_MASK);
- zl->fp = fopen (zl->filename, "a");
- save_errno = errno;
- umask(oldumask);
- if (zl->fp == NULL)
- {
- zlog_err("Log rotate failed: cannot open file %s for append: %s",
- zl->filename, safe_strerror(save_errno));
- return -1;
- }
- logfile_fd = fileno(zl->fp);
- zl->maxlvl[ZLOG_DEST_FILE] = level;
+ UNLOCK
+ return result;
+}
+
+void
+zlog_set_default_lvl (struct zlog *zl, int level)
+{
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->default_lvl = level;
}
- return 1;
+ UNLOCK
}
-
+
+/* Set logging level and default for all destinations */
+void
+zlog_set_default_lvl_dest (struct zlog *zl, int level)
+{
+ int i;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->default_lvl = level;
+
+ for (i = 0; i < ZLOG_NUM_DESTS; i++)
+ if (zl->maxlvl[i] != ZLOG_DISABLED)
+ zl->maxlvl[i] = level;
+ }
+
+ UNLOCK
+}
+
+int
+zlog_get_maxlvl (struct zlog *zl, zlog_dest_t dest)
+{
+ int result = ZLOG_DISABLED;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->maxlvl[dest];
+ }
+
+ UNLOCK
+ return result;
+}
+
+int
+zlog_get_facility (struct zlog *zl)
+{
+ int result = LOG_DAEMON;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->facility;
+ }
+
+ UNLOCK
+ return result;
+}
+
+void
+zlog_set_facility (struct zlog *zl, int facility)
+{
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->facility = facility;
+ }
+
+ UNLOCK
+}
+
+int
+zlog_get_record_priority (struct zlog *zl)
+{
+ int result = 0;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->record_priority;
+ }
+
+ UNLOCK
+ return result;
+}
+
+void
+zlog_set_record_priority (struct zlog *zl, int record_priority)
+{
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->record_priority = record_priority;
+ }
+ UNLOCK
+}
+
+int
+zlog_get_timestamp_precision (struct zlog *zl)
+{
+ int result = 0;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->timestamp_precision;
+ }
+ UNLOCK
+ return result;
+}
+
+void
+zlog_set_timestamp_precision (struct zlog *zl, int timestamp_precision)
+{
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ zl->timestamp_precision = timestamp_precision;
+ }
+
+ UNLOCK
+}
+
+/* returns name of ZLOG_NONE if no zlog given and no default set */
+const char *
+zlog_get_proto_name (struct zlog *zl)
+{
+ zlog_proto_t protocol = ZLOG_NONE;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ protocol = zl->protocol;
+ }
+
+ UNLOCK
+ return zlog_proto_names[protocol];
+}
+
+/* caller must free result */
+char *
+zlog_get_filename (struct zlog *zl)
+{
+ char * result = NULL;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL && zl->filename != NULL)
+ {
+ result = strdup(zl->filename);
+ }
+
+ UNLOCK
+ return result;
+}
+
+const char *
+zlog_get_ident (struct zlog *zl)
+{
+ const char * result = NULL;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = zl->ident;
+ }
+
+ UNLOCK
+ return result;
+}
+
+/* logging to a file? */
+int
+zlog_is_file (struct zlog *zl)
+{
+ int result = 0;
+
+ LOCK
+
+ if (zl == NULL)
+ zl = zlog_default;
+
+ if (zl != NULL)
+ {
+ result = (zl->fp != NULL);
+ }
+
+ UNLOCK
+ return result;
+}
+
/* Message lookup function. */
const char *
lookup (const struct message *mes, int key)