Mercurial > hg > freeDiameter
view libfdproto/msg_log.c @ 882:ae96ae28f3dd 1.1.5
Limit python version to avoid using python3 (not compatible)
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Sat, 03 Nov 2012 18:45:41 +0100 |
parents | edbdb35a603f |
children | fbf77629cb7b |
line wrap: on
line source
/********************************************************************************************************* * Software License Agreement (BSD License) * * Author: Sebastien Decugis <sdecugis@freediameter.net> * * * * Copyright (c) 2011, WIDE Project and NICT * * All rights reserved. * * * * Redistribution and use of this software in source and binary forms, with or without modification, are * * permitted provided that the following conditions are met: * * * * * Redistributions of source code must retain the above * * copyright notice, this list of conditions and the * * following disclaimer. * * * * * Redistributions in binary form must reproduce the above * * copyright notice, this list of conditions and the * * following disclaimer in the documentation and/or other * * materials provided with the distribution. * * * * * Neither the name of the WIDE Project or NICT nor the * * names of its contributors may be used to endorse or * * promote products derived from this software without * * specific prior written permission of WIDE Project and * * NICT. * * * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ /* messages logging facility */ #include "fdproto-internal.h" #include <stdarg.h> /* Configuration of this module */ static struct { struct { enum fd_msg_log_method meth; const char * metharg; } causes[FD_MSG_LOG_MAX + 1]; pthread_mutex_t lock; int init; struct dictionary *dict; } ml_conf = { .lock = PTHREAD_MUTEX_INITIALIZER, .init = 0 }; /* Initialize the module, with a dictionary to use to better parse the messages */ void fd_msg_log_init(struct dictionary *dict) { memset(&ml_conf.causes, 0, sizeof(ml_conf.causes)); ml_conf.init = 1; ml_conf.dict = dict; } /* Set a configuration property */ int fd_msg_log_config(enum fd_msg_log_cause cause, enum fd_msg_log_method method, const char * arg) { /* Check the parameters are valid */ TRACE_ENTRY("%d %d %p", cause, method, arg); CHECK_PARAMS( (cause >= 0) && (cause <= FD_MSG_LOG_MAX) ); CHECK_PARAMS( (method >= FD_MSG_LOGTO_DEBUGONLY) && (method <= FD_MSG_LOGTO_DIR) ); CHECK_PARAMS( (method == FD_MSG_LOGTO_DEBUGONLY) || (arg != NULL) ); /* Lock the configuration */ CHECK_POSIX( pthread_mutex_lock(&ml_conf.lock) ); if (!ml_conf.init) { ASSERT(0); } /* Now set the parameter */ ml_conf.causes[cause].meth = method; ml_conf.causes[cause].metharg = arg; if (method) { TRACE_DEBUG(INFO, "Logging %s messages set to %s '%s'", (cause == FD_MSG_LOG_DROPPED) ? "DROPPED" : (cause == FD_MSG_LOG_RECEIVED) ? "RECEIVED" : (cause == FD_MSG_LOG_SENT) ? "SENT" : "???", (method == FD_MSG_LOGTO_FILE) ? "file" : (method == FD_MSG_LOGTO_DIR) ? "directory" : "???", arg); } CHECK_POSIX( pthread_mutex_unlock(&ml_conf.lock) ); /* Done */ return 0; } /* Do not log anything within this one, since log lock is held */ static void fd_cleanup_mutex_silent( void * mutex ) { (void)pthread_mutex_unlock((pthread_mutex_t *)mutex); } /* Really log the message */ void fd_msg_log( enum fd_msg_log_cause cause, struct msg * msg, const char * prefix_format, ... ) { va_list ap; enum fd_msg_log_method meth; const char * metharg; FILE * fstr; char buftime[256]; size_t offset = 0; struct timespec ts; struct tm tm; TRACE_ENTRY("%d %p %p", cause, msg, prefix_format); CHECK_PARAMS_DO( (cause >= 0) && (cause <= FD_MSG_LOG_MAX), { TRACE_DEBUG(INFO, "Invalid cause received (%d)! Message was:", cause); fd_msg_dump_walk(INFO, msg); } ); /* First retrieve the config for this message */ CHECK_POSIX_DO( pthread_mutex_lock(&ml_conf.lock), ); if (!ml_conf.init) { ASSERT(0); } meth = ml_conf.causes[cause].meth; metharg = ml_conf.causes[cause].metharg; CHECK_POSIX_DO( pthread_mutex_unlock(&ml_conf.lock), ); /* Do not log if the level is not at least INFO */ if ((meth == FD_MSG_LOGTO_DEBUGONLY) && (fd_g_debug_lvl < INFO)) { return; } /* Get current time */ CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), /* continue */); offset += strftime(buftime + offset, sizeof(buftime) - offset, "%D,%T", localtime_r( &ts.tv_sec , &tm )); offset += snprintf(buftime + offset, sizeof(buftime) - offset, ".%6.6ld", ts.tv_nsec / 1000); /* Okay, now we will create the file descriptor */ switch (meth) { case FD_MSG_LOGTO_DEBUGONLY: fstr = fd_g_debug_fstr; break; case FD_MSG_LOGTO_FILE: TODO("Log to arg file"); TODO("Log a note to debug stream"); TRACE_DEBUG(INFO, "%s", metharg); break; case FD_MSG_LOGTO_DIR: TODO("Log to arg directory in a new file"); TODO("Log a note to debug stream"); break; } /* For file methods, let's parse the message so it looks better */ if (((meth != FD_MSG_LOGTO_DEBUGONLY) || (fd_g_debug_lvl > FULL)) && ml_conf.dict) { CHECK_FCT_DO( fd_msg_parse_dict( msg, ml_conf.dict, NULL ), ); } /* Then dump the prefix message to this stream, & to debug stream */ (void)pthread_mutex_lock(&fd_log_lock); pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock); va_start(ap, prefix_format); vfprintf( fstr, prefix_format, ap); va_end(ap); fflush(fstr); pthread_cleanup_pop(0); (void)pthread_mutex_unlock(&fd_log_lock); fd_log_debug_fstr(fstr, "\nLogged: %s\n\n", buftime); /* And now the message itself */ if ((meth == FD_MSG_LOGTO_DEBUGONLY) && (fd_g_debug_lvl <= INFO)) { /* dump only the header */ fd_msg_dump_fstr_one(msg, fstr); } else { /* dump the full content */ fd_msg_dump_fstr(msg, fstr); } /* And finally close the stream if needed */ switch (meth) { case FD_MSG_LOGTO_DEBUGONLY: break; case FD_MSG_LOGTO_FILE: TODO("close?"); break; case FD_MSG_LOGTO_DIR: TODO("close?"); break; } }