mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
splitted debug/log system out of utils and made it thread safe :-)
This commit is contained in:
parent
5f95fef037
commit
f2734a395e
8 changed files with 168 additions and 125 deletions
|
@ -1,7 +1,7 @@
|
|||
TARGETS = server send random receive test
|
||||
|
||||
# Common dependencies for all binaries
|
||||
OBJS = socket.o if.o utils.o msg.o node.o cfg.o tc.o hooks.o list.o path.o hist.o
|
||||
OBJS = socket.o if.o utils.o msg.o node.o cfg.o tc.o hooks.o list.o path.o hist.o log.o
|
||||
|
||||
VPATH = src
|
||||
|
||||
|
|
70
server/include/log.h
Normal file
70
server/include/log.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#ifndef _LOG_H_
|
||||
#define _LOG_H_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INDENT int __attribute__ ((__cleanup__(log_outdent), unused)) _old_indent = log_indent(1);
|
||||
#else
|
||||
#define INDENT ;
|
||||
#endif
|
||||
|
||||
/** Global debug level used by the debug() macro.
|
||||
* It defaults to V (defined by the Makefile) and can be
|
||||
* overwritten by the 'debug' setting in the config file.
|
||||
*/
|
||||
extern int _debug;
|
||||
|
||||
/** The log level which is passed as first argument to print() */
|
||||
enum log_level {
|
||||
DEBUG,
|
||||
INFO,
|
||||
WARN,
|
||||
ERROR
|
||||
};
|
||||
|
||||
int log_indent(int levels);
|
||||
|
||||
void log_outdent(int *);
|
||||
|
||||
/** Reset the wallclock of debugging outputs */
|
||||
void log_reset();
|
||||
|
||||
/** Logs variadic messages to stdout.
|
||||
*
|
||||
* @param lvl The log level
|
||||
* @param fmt The format string (printf alike)
|
||||
*/
|
||||
void log_print(enum log_level lvl, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
/** Printf alike debug message with level. */
|
||||
#define debug(lvl, msg, ...) do if (lvl <= _debug) log_print(DEBUG, msg, ##__VA_ARGS__); while (0)
|
||||
|
||||
/** Printf alike info message. */
|
||||
#define info(msg, ...) do log_print(INFO, msg, ##__VA_ARGS__); while (0)
|
||||
|
||||
/** Printf alike warning message. */
|
||||
#define warn(msg, ...) do log_print(WARN, msg, ##__VA_ARGS__); while (0)
|
||||
|
||||
/** Print error and exit. */
|
||||
#define error(msg, ...) do { \
|
||||
log_print(ERROR, msg, ##__VA_ARGS__); \
|
||||
die(); \
|
||||
} while (0)
|
||||
|
||||
/** Print error and strerror(errno). */
|
||||
#define serror(msg, ...) do { \
|
||||
log_print(ERROR, msg ": %s", ##__VA_ARGS__, strerror(errno)); \
|
||||
die(); \
|
||||
} while (0)
|
||||
|
||||
/** Print configuration error and exit. */
|
||||
#define cerror(c, msg, ...) do { \
|
||||
log_print(ERROR, msg " in %s:%u", ##__VA_ARGS__, \
|
||||
(config_setting_source_file(c)) ? \
|
||||
config_setting_source_file(c) : "(stdio)", \
|
||||
config_setting_source_line(c)); \
|
||||
die(); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _LOG_H_ */
|
||||
|
|
@ -39,14 +39,13 @@ struct path
|
|||
double rate;
|
||||
|
||||
/** A pointer to the last received message */
|
||||
struct msg *last;
|
||||
struct msg *current;
|
||||
/** A pointer to the previously received message */
|
||||
struct msg *previous;
|
||||
|
||||
/** Counter for received messages according to their sequence no displacement */
|
||||
struct hist histogram;
|
||||
|
||||
/** Last known message number */
|
||||
unsigned int sequence;
|
||||
|
||||
/** Counter for sent messages to all outgoing nodes */
|
||||
unsigned int sent;
|
||||
/** Counter for received messages from all incoming nodes */
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define EXPECT(x, v) __builtin_expect(x, v)
|
||||
|
@ -69,34 +72,16 @@
|
|||
b = tmp; \
|
||||
} while(0)
|
||||
|
||||
/** The log level which is passed as first argument to print() */
|
||||
enum log_level { DEBUG, INFO, WARN, ERROR };
|
||||
|
||||
/* Forward declarations */
|
||||
struct settings;
|
||||
struct timespec;
|
||||
|
||||
/* These global variables allow changing the output style and verbosity */
|
||||
extern int _debug;
|
||||
extern int _indent;
|
||||
|
||||
void outdent(int *old);
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define INDENT int __attribute__ ((__cleanup__(outdent), unused)) _old_indent = _indent++;
|
||||
#else
|
||||
#define INDENT ;
|
||||
#endif
|
||||
|
||||
/** Reset the wallclock of debugging outputs */
|
||||
void epoch_reset();
|
||||
|
||||
/** Logs variadic messages to stdout.
|
||||
*
|
||||
* @param lvl The log level
|
||||
* @param fmt The format string (printf alike)
|
||||
/** The main thread id.
|
||||
* This is used to notify the main thread about
|
||||
* the program termination.
|
||||
* See error() macros.
|
||||
*/
|
||||
void print(enum log_level lvl, const char *fmt, ...);
|
||||
extern pthread_t _mtid;
|
||||
|
||||
/** Safely append a format string to an existing string.
|
||||
*
|
||||
|
@ -123,9 +108,12 @@ double timespec_delta(struct timespec *start, struct timespec *end);
|
|||
/** Get period as timespec from rate */
|
||||
struct timespec timespec_rate(double rate);
|
||||
|
||||
/** A system(2) emulator with popen/pclose(2) and proper output handling */
|
||||
/** A system(2) emulator with popen / pclose(2) and proper output handling */
|
||||
int system2(const char* cmd, ...);
|
||||
|
||||
/** Call quit() in the main thread. */
|
||||
void die();
|
||||
|
||||
/** Check assertion and exit if failed. */
|
||||
#define assert(exp) do { \
|
||||
if (EXPECT(!exp, 0)) { \
|
||||
|
@ -134,43 +122,5 @@ int system2(const char* cmd, ...);
|
|||
exit(EXIT_FAILURE); \
|
||||
} } while (0)
|
||||
|
||||
/** Printf alike debug message with level. */
|
||||
#define debug(lvl, msg, ...) do { \
|
||||
if (lvl <= _debug) \
|
||||
print(DEBUG, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Printf alike info message. */
|
||||
#define info(msg, ...) do { \
|
||||
print(INFO, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Printf alike warning message. */
|
||||
#define warn(msg, ...) do { \
|
||||
print(WARN, msg, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** Print error and exit. */
|
||||
#define error(msg, ...) do { \
|
||||
print(ERROR, msg, ##__VA_ARGS__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
/** Print error and strerror(errno). */
|
||||
#define serror(msg, ...) do { \
|
||||
print(ERROR, msg ": %s", ##__VA_ARGS__, \
|
||||
strerror(errno)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
/** Print configuration error and exit. */
|
||||
#define cerror(c, msg, ...) do { \
|
||||
print(ERROR, msg " in %s:%u", ##__VA_ARGS__, \
|
||||
(config_setting_source_file(c)) ? \
|
||||
config_setting_source_file(c) : "(stdio)", \
|
||||
config_setting_source_line(c)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _UTILS_H_ */
|
||||
|
||||
|
|
69
server/src/log.c
Normal file
69
server/src/log.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
|
||||
int _debug = V;
|
||||
|
||||
static struct timespec epoch;
|
||||
|
||||
#ifdef __GNUC__
|
||||
static __thread int indent = 0;
|
||||
|
||||
/** Get thread-specific pointer to indent level */
|
||||
int log_indent(int levels)
|
||||
{
|
||||
int old = indent;
|
||||
indent += levels;
|
||||
return old;
|
||||
}
|
||||
|
||||
void log_outdent(int *old)
|
||||
{
|
||||
indent = *old;
|
||||
}
|
||||
#endif
|
||||
|
||||
void log_reset()
|
||||
{
|
||||
clock_gettime(CLOCK_REALTIME, &epoch);
|
||||
}
|
||||
|
||||
void log_print(enum log_level lvl, const char *fmt, ...)
|
||||
{
|
||||
struct timespec ts;
|
||||
char buf[512] = "";
|
||||
|
||||
va_list ap;
|
||||
|
||||
/* Timestamp */
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
strap(buf, sizeof(buf), "%8.3f ", timespec_delta(&epoch, &ts));
|
||||
|
||||
/* Severity */
|
||||
switch (lvl) {
|
||||
case DEBUG: strap(buf, sizeof(buf), BLD("%-5s "), GRY("Debug")); break;
|
||||
case INFO: strap(buf, sizeof(buf), BLD("%-5s "), " " ); break;
|
||||
case WARN: strap(buf, sizeof(buf), BLD("%-5s "), YEL(" Warn")); break;
|
||||
case ERROR: strap(buf, sizeof(buf), BLD("%-5s "), RED("Error")); break;
|
||||
}
|
||||
|
||||
/* Indention */
|
||||
#ifdef __GNUC__
|
||||
for (int i = 0; i < indent; i++)
|
||||
strap(buf, sizeof(buf), GFX("\x78") " ");
|
||||
strap(buf, sizeof(buf), GFX("\x74") " ");
|
||||
#endif
|
||||
|
||||
/* Format String */
|
||||
va_start(ap, fmt);
|
||||
vstrap(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Output */
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
OpalPrint("S2SS: %s\n", buf);
|
||||
#endif
|
||||
fprintf(stderr, "\r%s\n", buf);
|
||||
}
|
|
@ -153,7 +153,7 @@ int opal_read(struct node *n, struct msg *m)
|
|||
state = OpalGetAsyncModelState();
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP)) {
|
||||
info("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
exit(0);
|
||||
die();
|
||||
}
|
||||
|
||||
return -1; // FIXME: correct return value
|
||||
|
@ -195,7 +195,7 @@ int opal_read(struct node *n, struct msg *m)
|
|||
state = OpalGetAsyncModelState();
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP)) {
|
||||
info("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
exit(0);
|
||||
die();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -213,7 +213,7 @@ int opal_write(struct node *n, struct msg *m)
|
|||
state = OpalGetAsyncModelState();
|
||||
if ((state == STATE_RESET) || (state == STATE_STOP)) {
|
||||
info("OpalGetAsyncModelState(): Model stopped or resetted!");
|
||||
exit(0);
|
||||
die();
|
||||
}
|
||||
|
||||
OpalSetAsyncRecvIconStatus(m->sequence, o->recv_id); /* Set the Status to the message ID */
|
||||
|
|
|
@ -38,7 +38,7 @@ struct settings settings;
|
|||
config_t config;
|
||||
|
||||
static void quit()
|
||||
{ _indent = 0;
|
||||
{
|
||||
info("Stopping paths:");
|
||||
FOREACH(&paths, it)
|
||||
path_stop(it->path);
|
||||
|
@ -103,7 +103,6 @@ void signals_init()
|
|||
sigemptyset(&sa_quit.sa_mask);
|
||||
sigaction(SIGTERM, &sa_quit, NULL);
|
||||
sigaction(SIGINT, &sa_quit, NULL);
|
||||
atexit(&quit);
|
||||
}
|
||||
|
||||
void usage(const char *name)
|
||||
|
@ -118,11 +117,13 @@ void usage(const char *name)
|
|||
printf("Simulator2Simulator Server %s (built on %s, %s)\n",
|
||||
BLU(VERSION), MAG(__DATE__), MAG(__TIME__));
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
die();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
_mtid = pthread_self();
|
||||
|
||||
/* Check arguments */
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
if (argc != 2 && argc != 4)
|
||||
|
@ -130,8 +131,7 @@ int main(int argc, char *argv[])
|
|||
if (argc != 2)
|
||||
#endif
|
||||
usage(argv[0]);
|
||||
|
||||
epoch_reset();
|
||||
|
||||
info("This is Simulator2Simulator Server (S2SS) %s (built on %s, %s, debug=%d)",
|
||||
BLD(YEL(VERSION)), BLD(MAG(__DATE__)), BLD(MAG(__TIME__)), _debug);
|
||||
|
||||
|
@ -196,7 +196,7 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
pause();
|
||||
|
||||
/* Note: quit() is called by exit handler! */
|
||||
quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
#define RTLAB
|
||||
|
@ -24,20 +24,11 @@
|
|||
#include "cfg.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* This global variable contains the debug level for debug() and assert() macros */
|
||||
int _debug = V;
|
||||
int _indent = 0;
|
||||
pthread_t _mtid;
|
||||
|
||||
struct timespec epoch;
|
||||
|
||||
void outdent(int *old)
|
||||
void die()
|
||||
{
|
||||
_indent = *old;
|
||||
}
|
||||
|
||||
void epoch_reset()
|
||||
{
|
||||
clock_gettime(CLOCK_REALTIME, &epoch);
|
||||
pthread_kill(_mtid, SIGTERM);
|
||||
}
|
||||
|
||||
int strap(char *dest, size_t size, const char *fmt, ...)
|
||||
|
@ -59,42 +50,6 @@ int vstrap(char *dest, size_t size, const char *fmt, va_list ap)
|
|||
return vsnprintf(dest + len, size - len, fmt, ap);
|
||||
}
|
||||
|
||||
void print(enum log_level lvl, const char *fmt, ...)
|
||||
{
|
||||
struct timespec ts;
|
||||
char buf[512] = "";
|
||||
|
||||
va_list ap;
|
||||
|
||||
/* Timestamp */
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
strap(buf, sizeof(buf), "%8.3f ", timespec_delta(&epoch, &ts));
|
||||
|
||||
/* Severity */
|
||||
switch (lvl) {
|
||||
case DEBUG: strap(buf, sizeof(buf), BLD("%-5s "), GRY("Debug")); break;
|
||||
case INFO: strap(buf, sizeof(buf), BLD("%-5s "), " " ); break;
|
||||
case WARN: strap(buf, sizeof(buf), BLD("%-5s "), YEL(" Warn")); break;
|
||||
case ERROR: strap(buf, sizeof(buf), BLD("%-5s "), RED("Error")); break;
|
||||
}
|
||||
|
||||
/* Indention */
|
||||
for (int i = 0; i < _indent; i++)
|
||||
strap(buf, sizeof(buf), GFX("\x78") " ");
|
||||
strap(buf, sizeof(buf), GFX("\x74") " ");
|
||||
|
||||
/* Format String */
|
||||
va_start(ap, fmt);
|
||||
vstrap(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Output */
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
OpalPrint("S2SS: %s\n", buf);
|
||||
#endif
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
}
|
||||
|
||||
cpu_set_t to_cpu_set(int set)
|
||||
{
|
||||
cpu_set_t cset;
|
||||
|
|
Loading…
Add table
Reference in a new issue