Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
document last changes
[simgrid.git] / src / nws_portability / diagnostic.c
1 /* $Id$ */
2
3 #include "config_portability.h"
4
5 #include <stdarg.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <limits.h>
11
12 #include "diagnostic.h"
13 #include "osutil.h"
14 #include "strutil.h"
15
16 #define MAXRECORDS 2500
17
18 static FILE *diagDestinations[] =
19         {DIAGSUPPRESS, DIAGSUPPRESS, DIAGSUPPRESS,
20         DIAGSUPPRESS, DIAGSUPPRESS, DIAGSUPPRESS};
21 static long recordCounts[] =
22         {0, 0, 0, 0, 0, 0};
23 static void *lock = NULL;                       /* mutex for this modules */
24
25 /* we look quite extensively because I'm not quite sure what fprintf will
26  * do if the FILE* changes on the way */
27 static void
28 PrintDiagnostic(DiagLevels level,
29                 const char *message,
30                 va_list arguments) {
31
32         static const char *level_tags[] = {"", "", "Warning: ", "Error: ", "Fatal: ", "Debug: " };
33
34         /* we need a lock because we write recordCounts and we use
35          * diagDestinations[] */
36         if (GetNWSLock(&lock) == 0) {
37                 fprintf(stderr, "PrintDiagnostic: Error: Couldn't obtain the lock\n");
38         }
39         if(diagDestinations[level] != DIAGSUPPRESS) {
40                 if( (recordCounts[level]++ >= MAXRECORDS) &&
41                                 (diagDestinations[level] != stdout) &&
42                                 (diagDestinations[level] != stderr) ) {
43                 /* We want to avoid filling up the disk space when the
44                  * system is running for weeks at a time.  It might be
45                  * nice to save the old file under another name (maybe in
46                  * /tmp), then reopen.  That requires changing the
47                  * DirectDiagnostics() interface to take a file name
48                  * instead of a FILE *.  */
49                         rewind(diagDestinations[level]);
50                         recordCounts[level] = 0;
51                 }
52
53                 fprintf(diagDestinations[level], "%.0f %d ", CurrentTime(), (int)getpid());
54                 fprintf(diagDestinations[level], level_tags[level]);
55                 vfprintf(diagDestinations[level], message, arguments);
56                 fflush(diagDestinations[level]);
57         }
58         if (ReleaseNWSLock(&lock) == 0) {
59                 fprintf(stderr, "PrintDiagnostic: Error: Couldn't release the lock\n");
60         }
61 }
62
63
64 void
65 DirectDiagnostics(DiagLevels level,
66                   FILE *whereTo) {
67
68 #ifdef HAVE_FILENO
69         int f = 0;
70
71         /* just an extra check */
72         if (whereTo != NULL) {
73                 f = fileno(whereTo);
74         } 
75         if (f < 0) {
76                 PrintDiagnostic(DIAGERROR, "DirectDiagnostic: fileno failed", NULL);
77                 return;
78         }
79 #endif
80         GetNWSLock(&lock);
81         diagDestinations[level] = whereTo;
82         ReleaseNWSLock(&lock);
83 }
84
85
86 FILE *
87 DiagnosticsDirection(DiagLevels level) {
88         return diagDestinations[level];
89 }
90
91
92 void
93 PositionedDiagnostic(DiagLevels level,
94                      const char *fileName, 
95                      int line,
96                      const char *message,
97                      ...) {
98
99         va_list arguments;
100         char *extendedMessage;
101
102         /* we assume that NWS lines won't be past 10 digits */
103         extendedMessage = (char *)MALLOC(strnlen(fileName, MAX_FILENAME_LENGTH)
104                                 + strnlen(message, MAX_MESSAGE_LENGTH) + 11);
105         if (extendedMessage == NULL) {
106                 /* out of memory */
107                 PrintDiagnostic(DIAGERROR, "PositionedDiagnostic: out of memory", NULL);
108                 return;
109         }
110
111         va_start(arguments, message);
112         sprintf(extendedMessage, "%s:%d %s", fileName, line, message);
113         PrintDiagnostic(level, extendedMessage, arguments);
114         va_end(arguments);
115
116         free(extendedMessage);
117 }
118
119
120 void
121 Diagnostic(DiagLevels level,
122            const char *message,
123            ...) {
124         va_list arguments;
125
126         va_start(arguments, message);
127         PrintDiagnostic(level, message, arguments);
128         va_end(arguments);
129 }