Code_TYMPAN  4.4.0
Industrial site acoustic simulation
logging.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2014> <EDF-R&D> <FRANCE>
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  * See the GNU General Public License for more details.
11  * You should have received a copy of the GNU General Public License along
12  * with this program; if not, write to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
14  */
15 
16 #include <cstring>
17 #include <cstdarg>
18 #include <cstdlib>
19 #include <cstdio>
20 #include <string>
21 #include <sstream>
22 #include <vector>
23 
24 #ifdef _WIN32
25  #include <io.h>
26 #else
27  #include <glob.h>
28  #include <sys/types.h>
29  #include <sys/stat.h>
30  #include <unistd.h>
31 #endif // _WIN32
32 
33 #include "logging.h"
34 
35 using std::string;
36 using std::stringstream;
37 
38 // Initialise a NULL.
40 
41 #ifdef _DEBUG
42 static const bool bDebug = true;
43 #else
44 static const bool bDebug = false;
45 #endif
46 
47 // Adapted from URL below, which claims BSD license
48 // http://stackoverflow.com/questions/69738/c-how-to-get-fprintf-results-as-a-stdstring-w-o-sprintf
49 
50 static const size_t string_vformat_init_size = 1024;
51 static const size_t string_vformat_max_size = string_vformat_init_size * 8;
52 
53 // We want a static free function
54 static std::string string_vformat(const char* fmt, va_list ap)
55 {
56  // Allocate a buffer on the stack that's big enough for us almost
57  // all the time. Be prepared to allocate dynamically if it doesn't fit.
58  size_t size = string_vformat_init_size;
59  char stackbuf[string_vformat_init_size];
60  std::vector<char> dynamicbuf;
61  char* buf = &stackbuf[0];
62 
63  while (size <= string_vformat_max_size)
64  {
65  // Try to vsnprintf into our buffer.
66  int needed = vsnprintf(buf, size, fmt, ap);
67  // NB. C99 (which modern Linux and OS X follow) says vsnprintf
68  // failure returns the length it would have needed. But older
69  // glibc and current Windows return -1 for failure, i.e., not
70  // telling us how much was needed.
71 
72  if (needed <= (int)size && needed >= 0)
73  {
74  // It fit fine so we're done.
75  return std::string(buf, (size_t)needed);
76  }
77 
78  // vsnprintf reported that it wanted to write more characters
79  // than we allotted. So try again using a dynamic buffer. This
80  // doesn't happen very often if we chose our initial size well.
81  size = (needed > 0) ? (needed + 1) : (size * 2);
82  dynamicbuf.resize(size);
83  buf = &dynamicbuf[0];
84  }
85  // We exited the loop because the message size exceed the limit
86  // We force the null terminator and return the truncated message
87  dynamicbuf.back() = '\0';
88  buf = &dynamicbuf[0];
89  return std::string(buf);
90 }
91 
93 {
94  _ficTrace = NULL;
95 }
96 
98 
100 {
101  bool ret = _pInstance ? true : false;
102 
103  _pInstance = this;
104 
105  return ret;
106 }
107 
109 {
110  if (!_pInstance)
111  {
112  // Si pas d'instance definie comme singleton on en cree une
113  _pInstance = new OMessageManager();
114  }
115 
116  return _pInstance;
117 }
118 
119 void OMessageManager::warning(const char* message, ...)
120 {
121  va_list args = nullptr;
122  va_start(args, message);
123  vformat(MSG_WARNING, message, args);
124  va_end(args);
125 }
126 
127 void OMessageManager::error(const char* message, ...)
128 {
129  va_list args = nullptr;
130  va_start(args, message);
131  vformat(MSG_ERROR, message, args);
132  va_end(args);
133 }
134 
135 void OMessageManager::fatal(const char* message, ...)
136 {
137  va_list args = nullptr;
138  va_start(args, message);
139  vformat(MSG_FATAL, message, args);
140  va_end(args);
141 }
142 
143 void OMessageManager::info(const char* message, ...)
144 {
145  va_list args = nullptr;
146  va_start(args, message);
147  vformat(MSG_INFO, message, args);
148  va_end(args);
149 }
150 
151 void OMessageManager::debug(const char* message, ...)
152 {
153  if (bDebug)
154  {
155  va_list args = nullptr;
156  va_start(args, message);
157  vformat(MSG_DEBUG, message, args);
158  va_end(args);
159  }
160 }
161 
162 void OMessageManager::missingFile(const char* nomFic)
163 {
164  error("Fichier %s introuvable", nomFic);
165 }
166 
167 void OMessageManager::toDo(const char* message)
168 {
169  printf("%s non implemente.\n", message);
170 }
171 
172 void OMessageManager::trace(const char* message, ...)
173 {
174  va_list args = nullptr;
175  va_start(args, message);
176 
177  if (initTrace())
178  {
179  fprintf(_ficTrace, "TRACE %s : ", getStrDate());
180  vfprintf(_ficTrace, message, args);
181  fprintf(_ficTrace, "\n");
182  fflush(_ficTrace);
183  }
184 
185  va_end(args);
186 }
187 
188 void OMessageManager::warning(const QString& message, ...)
189 {
190  va_list args = nullptr;
191 
192 #ifdef _WIN32
193  // CLM-NT35: Pb en debug avec string cast
194  QByteArray mess_tmp = message.toUtf8();
195  char* mymessage = (char*)mess_tmp.data();
196  args = (va_list)(&message + 1);
197 #else
198  char* mymessage = message.toUtf8().data();
199  va_start(args, message);
200 #endif
201 
202  vformat(MSG_WARNING, mymessage, args);
203  va_end(args);
204 }
205 
206 void OMessageManager::error(const QString& message, ...)
207 {
208  va_list args = nullptr;
209 
210 #ifdef _WIN32
211  // CLM-NT35: Pb en debug avec string cast
212  QByteArray mess_tmp = message.toUtf8();
213  char* mymessage = (char*)mess_tmp.data();
214  args = (va_list)(&message + 1);
215 #else
216  char* mymessage = message.toUtf8().data();
217  va_start(args, message);
218 #endif
219 
220  vformat(MSG_ERROR, mymessage, args);
221  va_end(args);
222 }
223 
224 void OMessageManager::fatal(const QString& message, ...)
225 {
226  va_list args = nullptr;
227 
228 #ifdef _WIN32
229  // CLM-NT35: Pb en debug avec string cast
230  QByteArray mess_tmp = message.toUtf8();
231  char* mymessage = (char*)mess_tmp.data();
232  args = (va_list)(&message + 1);
233 #else
234  char* mymessage = message.toUtf8().data();
235  va_start(args, message);
236 #endif
237 
238  vformat(MSG_FATAL, mymessage, args);
239  va_end(args);
240 }
241 
242 void OMessageManager::info(const QString& message, ...)
243 {
244  va_list args = nullptr;
245 
246 #ifdef _WIN32
247  // CLM-NT35: Pb en debug avec string cast
248  QByteArray mess_tmp = message.toUtf8();
249  char* mymessage = (char*)mess_tmp.data();
250  args = (va_list)(&message + 1);
251 #else
252  char* mymessage = message.toUtf8().data();
253  va_start(args, message);
254 #endif
255 
256  vformat(MSG_INFO, mymessage, args);
257  va_end(args);
258 }
259 
260 void OMessageManager::debug(const QString& message, ...)
261 {
262  va_list args = nullptr;
263 
264 #ifdef _WIN32
265  // CLM-NT35: Pb en debug avec string cast
266  QByteArray mess_tmp = message.toUtf8();
267  char* mymessage = (char*)mess_tmp.data();
268  args = (va_list)(&message + 1);
269 #else
270  char* mymessage = message.toUtf8().data();
271  va_start(args, message);
272 #endif
273  vformat(MSG_DEBUG, mymessage, args);
274  va_end(args);
275 }
276 
277 void OMessageManager::missingFile(const QString& nomFic)
278 {
279  error("Fichier %s introuvable", nomFic.toUtf8().data());
280 }
281 
282 void OMessageManager::toDo(const QString& message)
283 {
284  printf("%s non implemente.\n", message.toUtf8().data());
285 }
286 
287 void OMessageManager::trace(const QString& message, ...)
288 {
289  va_list args = nullptr;
290 
291 #ifdef _WIN32
292  // CLM-NT35: Pb en debug avec string cast
293  QByteArray mess_tmp = message.toUtf8();
294  char* mymessage = (char*)mess_tmp.data();
295  args = (va_list)(&message + 1);
296 #else
297  char* mymessage = message.toUtf8().data();
298  va_start(args, message);
299 #endif
300 
301  trace(mymessage, args);
302  va_end(args);
303 }
304 
305 void OMessageManager::format(int level, const char* message, ...)
306 {
307  va_list args = nullptr;
308  va_start(args, message);
309  vformat(level, message, args);
310  va_end(args);
311 }
312 
313 void OMessageManager::vformat(int level, const char* message, va_list args)
314 {
315  if ((!bDebug) && (level == MSG_DEBUG))
316  {
317  return;
318  } // on n'affiche les msg debug qu'en mode debug...
319 
320  stringstream msg;
321 
322  // On construit le msg de la facon suivante :
323  // JJ/MM/AAAA HH:MM:SS <niveau> <message> <retour a la ligne>
324  msg << getStrDate() << " ";
325  switch (level)
326  {
327  case MSG_DEBUG:
328  msg << "Debug";
329  break;
330  case MSG_BENCH:
331  msg << "Bench";
332  break;
333  case MSG_INFO:
334  msg << "Info";
335  break;
336  case MSG_WARNING:
337  msg << "Warning";
338  break;
339  case MSG_ERROR:
340  msg << "Erreur";
341  break;
342  case MSG_FATAL:
343  msg << "Erreur Fatale";
344  break;
345  default:
346  break;
347  }
348  msg << " : ";
349  msg << string_vformat(message, args);
350  msg << std::endl;
351 
352  // Affichage/ecriture du message
353  output(msg.str().c_str(), level);
354 }
355 
356 void OMessageManager::output(const char* message, int level)
357 {
358  if ((!bDebug) && (level == MSG_DEBUG))
359  {
360  return;
361  }
362 
363  FILE* outputStream = 0;
364 
365  switch (level)
366  {
367  case MSG_WARNING:
368  case MSG_ERROR:
369  case MSG_FATAL:
370  outputStream = stderr;
371  break;
372  case MSG_DEBUG:
373  case MSG_BENCH:
374  case MSG_INFO:
375  default:
376  outputStream = stdout;
377  break;
378  }
379 
380  fprintf(outputStream, "%s", message);
381 }
382 
384 {
385  time_t thetime = 0;
386  struct tm buf;
387  char fileName[100];
388  time(&thetime);
389 #ifdef _WIN32
390  intptr_t hFile = 0;
391  struct _finddata_t c_file;
392  if ((hFile = _findfirst("c:\\Trace*.*", &c_file)) !=
393  -1L) // Attention: 20/02/01 LM : change le nom du fichier mais faudra mettre un truc pour parametrer
394  // ce nom
395  {
396  checkFile(&c_file, thetime);
397  while (_findnext(hFile, &c_file) == 0)
398  {
399  checkFile(&c_file, thetime);
400  }
401  _findclose(hFile);
402  }
403 #else
404  glob_t globbuf;
405  if (0 == glob("/Trace*.*", 0, NULL, &globbuf))
406  {
407  for (int i = 0; i < globbuf.gl_pathc; i++)
408  {
409  checkFile(globbuf.gl_pathv[i], thetime);
410  }
411  globfree(&globbuf);
412  }
413 
414 #endif
415 
416  gmtime_s(&buf, &thetime);
417 #ifdef _WIN32
418  sprintf_s(fileName, "c:\\Trace%.3d.txt",
419  buf.tm_yday); // Attention: 20/02/01 LM : change le nom du fichier mais faudra
420  // mettre un truc pour parametrer ce nom
421 #else
422  sprintf_s(fileName, "/Trace%.3d.txt",
423  buf.tm_yday); // Attention: 20/02/01 LM : change le nom du fichier mais faudra
424  // mettre un truc pour parametrer ce nom
425 #endif
426  if (_ficTrace == NULL)
427  {
428  FILE* filepoint = nullptr;
429  if ((fopen_s(&filepoint, fileName, "at")) != 0)
430  {
431  fprintf_s(_ficTrace, "ERROR : cannot open file '%s'\n", fileName);
432  }
433  else
434  {
435  fprintf_s(_ficTrace,
436  "-------------------------------------------------------------------------\n");
437  }
438  }
439 
440  return (_ficTrace != NULL);
441 }
442 
444 {
445  static char sDate[100];
446  time_t Date = 0;
447 
448  time(&Date);
449  struct tm buf;
450  localtime_s(&buf, &Date);
451  strftime(sDate, sizeof(sDate), "%d/%m/%Y - %H:%M:%S", &buf);
452 
453  return (sDate);
454 }
455 
456 #ifdef _WIN32
457 void OMessageManager::checkFile(struct _finddata_t* c_file, time_t theTime)
458 {
459  if (difftime(theTime, c_file->time_create) > 604800) // Une semaine
460  {
461  remove(c_file->name);
462  }
463 }
464 #else
465 void OMessageManager::checkFile(const char* c_file, time_t theTime)
466 {
467  struct stat buf;
468 
469  stat(c_file, &buf);
470  if (difftime(theTime, buf.st_ctime) > 604800) // Une semaine
471  {
472  remove(c_file);
473  }
474 }
475 #endif
virtual void debug(const char *message,...)
Definition: logging.cpp:151
virtual void output(const char *message, int level)
Definition: logging.cpp:356
virtual void missingFile(const char *nomFic)
Definition: logging.cpp:162
static char * getStrDate()
Definition: logging.cpp:443
void vformat(int level, const char *message, va_list args)
Variable argument list version of format.
Definition: logging.cpp:313
virtual void warning(const char *message,...)
Definition: logging.cpp:119
virtual void error(const char *message,...)
Definition: logging.cpp:127
virtual ~OMessageManager()
Definition: logging.cpp:97
static LPOMessageManager _pInstance
Instance unique du singleton.
Definition: logging.h:208
virtual int initTrace()
Definition: logging.cpp:383
FILE * _ficTrace
Le fichier de trace.
Definition: logging.h:204
virtual void trace(const char *message,...)
Definition: logging.cpp:172
bool setAsSingleton()
Definition: logging.cpp:99
virtual void fatal(const char *message,...)
Definition: logging.cpp:135
static OMessageManager * get()
Definition: logging.cpp:108
virtual void format(int level, const char *message,...)
Definition: logging.cpp:305
static void checkFile(const char *c_file, time_t theTime)
Definition: logging.cpp:465
virtual void toDo(const char *message)
Definition: logging.cpp:167
virtual void info(const char *message,...)
Definition: logging.cpp:143
#define MSG_DEBUG
Definition: logging.h:25
#define MSG_INFO
Definition: logging.h:27
#define MSG_BENCH
Definition: logging.h:26
#define MSG_FATAL
Definition: logging.h:30
#define MSG_WARNING
Definition: logging.h:28
#define MSG_ERROR
Definition: logging.h:29