NCBI C++ ToolKit
ftaerr.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #include <ncbi_pch.hpp>
2 
3 #include <string.h>
4 #include <time.h>
5 #include <sstream>
6 
7 #include <corelib/ncbiapp.hpp>
8 #include <corelib/ncbifile.hpp>
9 
11 #include "ftaerr.hpp"
12 #include "ftacpp.hpp"
13 
14 #ifdef THIS_FILE
15 # undef THIS_FILE
16 #endif
17 #define THIS_FILE "ftaerr.cpp"
18 
19 #define MESSAGE_DIR "/am/ncbiapdata/errmsg"
20 
21 
24 
25 struct FtaErrCode {
26  const char* module = nullptr;
27  const char* fname = nullptr;
28  int line = 0;
29 };
30 
32  string strsubtag;
33  int intsubtag = -1;
34  int intseverity = -1;
35  FtaMsgModTagCtx* next = nullptr;
36 
37  ~FtaMsgModTagCtx() { delete next; };
38 };
39 
40 struct FtaMsgModTag {
41  string strtag;
42  int inttag = 0;
43  FtaMsgModTagCtx* bmctx = nullptr;
44  FtaMsgModTag* next = nullptr;
45 
47  {
48  delete bmctx;
49  delete next;
50  };
51 };
52 
54  string modname; /* NCBI_MODULE or THIS_MODULE value */
55  string filename; /* Name with full path of .msg file */
56  FtaMsgModTag* bmmt = nullptr;
57  FtaMsgModFiles* next = nullptr;
58 
60  {
61  delete bmmt;
62  delete next;
63  };
64 };
65 
66 
67 struct FtaMsgPost {
68  FILE* lfd; /* Opened logfile */
69  string logfile; /* Logfile full name */
70  string appname;
72  string prefix_locus;
74  bool to_stderr;
79  bool hook_only;
80  ErrSev msglevel; /* Filter out messages displaying on
81  stderr only: ignode those with
82  severity lower than msglevel */
83  ErrSev loglevel; /* Filter out messages displaying in
84  logfile only: ignode those with
85  severity lower than msglevel */
86  FtaMsgModFiles* bmmf = nullptr;
87 
89  lfd(nullptr),
90  logfile(),
92  prefix_locus(),
94  to_stderr(true),
102  {
103  }
104 
105  virtual ~FtaMsgPost()
106  {
107  if (lfd) {
108  fclose(lfd);
109  }
110  logfile.clear();
111  prefix_locus.clear();
112  prefix_accession.clear();
113  prefix_feature.clear();
114  delete bmmf;
115  };
116 };
117 
118 const char* months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
119 
120 thread_local unique_ptr<FtaMsgPost> bmp;
122 
123 /**********************************************************/
124 static int FtaStrSevToIntSev(const string& strsevcode)
125 {
126  if (strsevcode.empty())
127  return -1;
128 
129  static const map<string, int> sStringToInt = { { "SEV_INFO", 1 },
130  { "SEV_WARNING", 2 },
131  { "SEV_ERROR", 3 },
132  { "SEV_REJECT", 4 },
133  { "SEV_FATAL", 5 } };
134 
135  if (auto it = sStringToInt.find(strsevcode);
136  it != sStringToInt.end()) {
137  return it->second;
138  }
139 
140  return -1;
141 }
142 
143 /**********************************************************/
145  const char* module, int code, int subcode, string& strcode, string& strsubcode, int& sevcode)
146 {
147  FtaMsgModTagCtx* bmctxp;
148  FtaMsgModFiles* bmmfp;
149  FtaMsgModTag* bmmtp;
150  FILE* fd;
151 
152  char* p;
153  char* q;
154  char s[2048];
155  char ch;
156  bool got_mod;
157 
158  if (! bmp)
159  FtaErrInit();
160 
161  for (got_mod = false, bmmfp = bmp->bmmf; bmmfp; bmmfp = bmmfp->next) {
162  if (bmmfp->modname != module) {
163  continue;
164  }
165 
166  got_mod = true;
167  for (bmmtp = bmmfp->bmmt; bmmtp; bmmtp = bmmtp->next) {
168  if (bmmtp->inttag != code)
169  continue;
170 
171  strcode = bmmtp->strtag;
172  for (bmctxp = bmmtp->bmctx; bmctxp; bmctxp = bmctxp->next) {
173  if (bmctxp->intsubtag != subcode)
174  continue;
175 
176  strsubcode = bmctxp->strsubtag;
177  sevcode = bmctxp->intseverity;
178  break;
179  }
180  break;
181  }
182  break;
183  }
184 
185  if (got_mod)
186  return;
187 
188  string curdir = CDir::GetCwd();
189  string buf = curdir + CDir::GetPathSeparator() + module + ".msg";
190  fd = fopen(buf.c_str(), "r");
191  if (! fd) {
192  buf = string(MESSAGE_DIR) + CDir::GetPathSeparator() + module + ".msg";
193  fd = fopen(buf.c_str(), "r");
194  if (! fd) {
195  return;
196  }
197  }
198 
199  bmmfp = new FtaMsgModFiles;
200  bmmfp->modname = module;
201  bmmfp->filename = buf;
202 
203  if (bmp->bmmf)
204  bmmfp->next = bmp->bmmf;
205  bmp->bmmf = bmmfp;
206 
207  bmmtp = nullptr;
208  while (fgets(s, 2047, fd)) {
209  if (s[0] != '$' || (s[1] != '^' && s[1] != '$'))
210  continue;
211 
212  string val1;
213  string val3;
214  int val2{ 0 };
215 
216  for (p = s + 2; *p == ' ' || *p == '\t'; p++) {}
217  for (q = p; *p && *p != ','; p++) {}
218  if (*p != ',')
219  continue;
220 
221  *p = '\0';
222  val1 = q;
223 
224  for (*p++ = ','; *p == ' ' || *p == '\t'; p++) {}
225  for (q = p; *p >= '0' && *p <= '9'; p++) {}
226 
227  if (q == p) {
228  continue;
229  }
230 
231  ch = *p;
232  *p = '\0';
233  val2 = atoi(q);
234  *p = ch;
235 
236  if (val2 < 1) {
237  continue;
238  }
239 
240  if (s[1] == '^' && ch == ',') {
241  for (p++; *p == ' ' || *p == '\t'; p++) {}
242  for (q = p;
243  *p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ',';
244  p++) {}
245  if (p > q) {
246  ch = *p;
247  *p = '\0';
248  if (! strcmp(q, "SEV_INFO") || ! strcmp(q, "SEV_WARNING") ||
249  ! strcmp(q, "SEV_ERROR") || ! strcmp(q, "SEV_REJECT") ||
250  ! strcmp(q, "SEV_FATAL")) {
251  val3 = q;
252  }
253  *p = ch;
254  }
255  }
256 
257  if (s[1] == '$') {
258  bmmtp = new FtaMsgModTag;
259  if (bmmfp->bmmt)
260  bmmtp->next = bmmfp->bmmt;
261  bmmfp->bmmt = bmmtp;
262 
263  bmmtp->strtag = val1;
264  bmmtp->inttag = val2;
265  if (val2 == code && strcode.empty())
266  strcode = val1;
267 
268  continue;
269  }
270 
271  if (! bmmfp->bmmt || ! bmmtp) {
272  continue;
273  }
274 
275  bmctxp = new FtaMsgModTagCtx;
276  if (bmmtp->bmctx)
277  bmctxp->next = bmmtp->bmctx;
278  bmmtp->bmctx = bmctxp;
279 
280  bmctxp->strsubtag = val1;
281  bmctxp->intsubtag = val2;
282  bmctxp->intseverity = FtaStrSevToIntSev(val3);
283 
284  if (val2 == subcode && strsubcode.empty() && ! strcode.empty()) {
285  strsubcode = val1;
286  if (sevcode < 0)
287  sevcode = bmctxp->intseverity;
288  }
289  }
290 
291  fclose(fd);
292 }
293 
294 /**********************************************************/
296 {
297  if (bmp)
298  return;
299 
300  bmp.reset(new FtaMsgPost());
301  bmp->appname = CNcbiApplication::GetAppName();
302 
303  fec.module = nullptr;
304  fec.fname = nullptr;
305  bmp->hook_only = false;
306  fec.line = -1;
307 }
308 
309 /**********************************************************/
310 void FtaErrFini(void)
311 {
312  if (bmp) {
313  bmp.reset();
314  }
315 }
316 
317 
318 /**********************************************************/
319 void FtaInstallPrefix(int prefix, const char* name, const char* location)
320 {
321  if (! name || *name == '\0')
322  return;
323 
325  bmp->prefix_accession = name;
326  }
327  if ((prefix & PREFIX_LOCUS) == PREFIX_LOCUS) {
328  bmp->prefix_locus = name;
329  }
330  if ((prefix & PREFIX_FEATURE) == PREFIX_FEATURE) {
331  char tmp[160];
332  strcpy(tmp, "FEAT=");
333  strncat(tmp, name, 20);
334  tmp[24] = '\0';
335  strcat(tmp, "[");
336  strncat(tmp, location, 127);
337  tmp[152] = '\0';
338  strcat(tmp, "]");
339  bmp->prefix_feature = tmp;
340  }
341 }
342 
343 /**********************************************************/
345 {
347  bmp->prefix_accession.clear();
348  }
349  if ((prefix & PREFIX_LOCUS) == PREFIX_LOCUS) {
350  bmp->prefix_locus.clear();
351  }
352  if ((prefix & PREFIX_FEATURE) == PREFIX_FEATURE) {
353  bmp->prefix_feature.clear();
354  }
355 }
356 
357 /**********************************************************/
358 bool ErrSetLog(const char* logfile)
359 {
360  struct tm* tm;
361  time_t now;
362  int i;
363 
364  if (! logfile || ! *logfile)
365  return (false);
366 
367  if (! bmp)
368  FtaErrInit();
369 
370  if (bmp->logfile.empty()) {
371  bmp->logfile = logfile;
372  }
373 
374  if (! bmp->lfd && ! bmp->logfile.empty()) {
375  time(&now);
376  tm = localtime(&now);
377  i = tm->tm_hour % 12;
378  if (! i)
379  i = 12;
380 
381  bmp->lfd = fopen(bmp->logfile.c_str(), "a");
382  fprintf(bmp->lfd,
383  "\n========================[ %s %d, %d %2d:%02d %s ]========================\n",
384  months[tm->tm_mon],
385  tm->tm_mday,
386  tm->tm_year + 1900,
387  i,
388  tm->tm_min,
389  (tm->tm_hour >= 12) ? "PM" : "AM");
390  }
391 
392  return (true);
393 }
394 
395 /**********************************************************/
397 {
398 }
399 
400 /**********************************************************/
402 {
403  if (! bmp)
404  FtaErrInit();
405 
406  if ((flags & EO_MSG_CODES) == EO_MSG_CODES)
407  bmp->show_msg_codes = true;
408  if ((flags & EO_LOG_CODES) == EO_LOG_CODES)
409  bmp->show_log_codes = true;
411  bmp->show_msg_codeline = true;
413  bmp->show_log_codeline = true;
414 }
415 
416 /**********************************************************/
417 void ErrClear(void)
418 {
419 }
420 
421 /**********************************************************/
422 void ErrLogPrintStr(const char* str)
423 {
424  if (! str || str[0] == '\0')
425  return;
426 
427  if (! bmp)
428  FtaErrInit();
429 
430  fprintf(bmp->lfd, "%s", str);
431 }
432 
433 /**********************************************************/
435 {
436  ErrSev prev;
437 
438  if (! bmp)
439  FtaErrInit();
440 
441  prev = bmp->loglevel;
442  bmp->loglevel = sev;
443  return (prev);
444 }
445 
446 /**********************************************************/
448 {
449  ErrSev prev;
450 
451  if (! bmp)
452  FtaErrInit();
453 
454  prev = bmp->msglevel;
455  bmp->msglevel = sev;
456  return (prev);
457 }
458 
459 /**********************************************************/
460 void Nlm_ErrSetContext(const char* module, const char* fname, int line)
461 {
462  if (! bmp)
463  FtaErrInit();
464 
465  fec.module = module;
466  fec.fname = fname;
467  fec.line = line;
468 }
469 
470 /**********************************************************/
472 {
473  EDiagSev cxx_severity;
474 
475  switch (c_severity) {
476  case SEV_NONE:
477  cxx_severity = eDiag_Trace;
478  break;
479  case SEV_INFO:
480  cxx_severity = eDiag_Info;
481  break;
482  case SEV_WARNING:
483  cxx_severity = eDiag_Warning;
484  break;
485  case SEV_ERROR:
486  cxx_severity = eDiag_Error;
487  break;
488  case SEV_REJECT:
489  cxx_severity = eDiag_Critical;
490  break;
491  case SEV_FATAL:
492  default:
493  cxx_severity = eDiag_Fatal;
494  break;
495  }
496  return (cxx_severity);
497 }
498 
499 /**********************************************************/
500 void Nlm_ErrPostEx(ErrSev sev, int lev1, int lev2, const char* fmt, ...)
501 {
502  if (! bmp)
503  FtaErrInit();
504 
505  if (! fec.fname || fec.line < 0) {
506  fec.module = nullptr;
507  fec.fname = nullptr;
508  fec.line = -1;
509  return;
510  }
511 
512  va_list args;
513  char fpiBuffer[1024];
514  va_start(args, fmt);
515  vsnprintf(fpiBuffer, 1024, fmt, args);
516  va_end(args);
517 
518  int fpiSevcode = -1;
519  int fpiIntcode = lev1;
520  int fpiIntsubcode = lev2;
521 
522  string fpiStrcode;
523  string fpiStrsubcode;
524 
525  int fpiLine = fec.line;
526  const char* fpiFname = fec.fname;
527  const char* fpiModule = fec.module;
528 
529  fec.module = nullptr;
530  fec.fname = nullptr;
531  fec.line = -1;
532 
533  if (fpiModule && *fpiModule)
534  FtaErrGetMsgCodes(fpiModule, fpiIntcode, fpiIntsubcode, fpiStrcode, fpiStrsubcode, fpiSevcode);
535  else
536  fpiModule = nullptr;
537 
538  if (fpiSevcode < 0)
539  fpiSevcode = (int)sev;
540 
541  if (bmp->appname.empty())
542  bmp->appname = CNcbiApplication::GetAppName();
543 
544  stringstream textStream;
545  if (! fpiStrcode.empty()) {
546  textStream << "[" << fpiStrcode.c_str();
547  if (! fpiStrsubcode.empty()) {
548  textStream << "." << fpiStrsubcode.c_str();
549  }
550  textStream << "] ";
551  }
552 
553  if (bmp->show_log_codeline) {
554  textStream << "{" << fpiFname << ", line " << fpiLine;
555  }
556  if (! bmp->prefix_locus.empty()) {
557  textStream << bmp->prefix_locus << ": ";
558  }
559  if (! bmp->prefix_accession.empty()) {
560  textStream << bmp->prefix_accession << ": ";
561  }
562  if (! bmp->prefix_feature.empty()) {
563  textStream << bmp->prefix_feature << " ";
564  }
565  textStream << fpiBuffer;
566 
567  static const map<ErrSev, EDiagSev> sSeverityMap = { { SEV_NONE, eDiag_Trace },
568  { SEV_INFO, eDiag_Info },
570  { SEV_ERROR, eDiag_Error },
572  { SEV_FATAL, eDiag_Fatal } };
573 
575  .Report(fpiModule ? fpiModule : "",
576  sSeverityMap.at(static_cast<ErrSev>(fpiSevcode)),
577  lev1,
578  lev2,
579  textStream.str());
580 }
581 
582 /**********************************************************/
583 void Nlm_ErrPostStr(ErrSev sev, int lev1, int lev2, const char* str)
584 {
585  Nlm_ErrPostEx(sev, lev1, lev2, str);
586 }
587 
588 /**********************************************************/
589 
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
static CFlatFileMessageReporter & GetInstance()
void Report(const string &module, EDiagSev severity, int code, int subcode, const string &text, int lineNum=-1)
const_iterator end() const
Definition: map.hpp:152
const_iterator find(const key_type &key) const
Definition: map.hpp:153
static const char location[]
Definition: config.c:97
static uch flags
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
USING_SCOPE(objects)
bool ErrSetLog(const char *logfile)
Definition: ftaerr.cpp:358
void ErrClear(void)
Definition: ftaerr.cpp:417
void Nlm_ErrPostStr(ErrSev sev, int lev1, int lev2, const char *str)
Definition: ftaerr.cpp:583
ErrSev ErrSetLogLevel(ErrSev sev)
Definition: ftaerr.cpp:434
void FtaDeletePrefix(int prefix)
Definition: ftaerr.cpp:344
void FtaErrGetMsgCodes(const char *module, int code, int subcode, string &strcode, string &strsubcode, int &sevcode)
Definition: ftaerr.cpp:144
void Nlm_ErrSetContext(const char *module, const char *fname, int line)
Definition: ftaerr.cpp:460
thread_local unique_ptr< FtaMsgPost > bmp
Definition: ftaerr.cpp:120
const char * months[]
Definition: ftaerr.cpp:118
void ErrSetFatalLevel(ErrSev sev)
Definition: ftaerr.cpp:396
FtaErrCode fec
Definition: ftaerr.cpp:121
void ErrSetOptFlags(int flags)
Definition: ftaerr.cpp:401
void FtaErrInit()
Definition: ftaerr.cpp:295
ErrSev ErrSetMessageLevel(ErrSev sev)
Definition: ftaerr.cpp:447
EDiagSev ErrCToCxxSeverity(int c_severity)
Definition: ftaerr.cpp:471
static int FtaStrSevToIntSev(const string &strsevcode)
Definition: ftaerr.cpp:124
#define MESSAGE_DIR
Definition: ftaerr.cpp:19
void ErrLogPrintStr(const char *str)
Definition: ftaerr.cpp:422
void FtaErrFini(void)
Definition: ftaerr.cpp:310
void Nlm_ErrPostEx(ErrSev sev, int lev1, int lev2, const char *fmt,...)
Definition: ftaerr.cpp:500
void FtaInstallPrefix(int prefix, const char *name, const char *location)
Definition: ftaerr.cpp:319
#define PREFIX_FEATURE
Definition: ftaerr.hpp:16
#define EO_MSG_CODES
Definition: ftaerr.hpp:20
#define PREFIX_LOCUS
Definition: ftaerr.hpp:15
#define EO_LOG_FILELINE
Definition: ftaerr.hpp:25
#define EO_LOG_CODES
Definition: ftaerr.hpp:21
#define EO_MSG_FILELINE
Definition: ftaerr.hpp:24
#define PREFIX_ACCESSION
Definition: ftaerr.hpp:14
#define SEV_INFO
Definition: gicache.c:89
#define SEV_WARNING
Definition: gicache.c:90
#define SEV_ERROR
Definition: gicache.c:91
#define SEV_NONE
Definition: gicache.c:88
#define SEV_FATAL
Definition: gicache.c:93
#define SEV_REJECT
Definition: gicache.c:92
static string GetAppName(EAppNameType name_type=eBaseName, int argc=0, const char *const *argv=NULL)
Definition: ncbiapp.cpp:1357
string
Definition: cgiapp.hpp:687
ErrSev
Definition: ncbierr.hpp:63
EDiagSev
Severity level for the posted diagnostics.
Definition: ncbidiag.hpp:650
@ eDiag_Trace
Trace message.
Definition: ncbidiag.hpp:657
@ eDiag_Info
Informational message.
Definition: ncbidiag.hpp:651
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
@ eDiag_Warning
Warning message.
Definition: ncbidiag.hpp:652
@ eDiag_Fatal
Fatal error – guarantees exit(or abort)
Definition: ncbidiag.hpp:655
@ eDiag_Critical
Critical error message.
Definition: ncbidiag.hpp:654
static char GetPathSeparator(void)
Get path separator symbol specific for the current platform.
Definition: ncbifile.cpp:433
static string GetCwd(void)
Get the current working directory.
Definition: ncbifile.cpp:3708
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
char * buf
int i
int strcmp(const char *str1, const char *str2)
Definition: odbc_utils.hpp:160
Defines the CNcbiApplication and CAppException classes for creating NCBI applications.
#define vsnprintf
Definition: ncbiconf_msvc.h:66
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
#define nullptr
Definition: ncbimisc.hpp:45
static char tmp[2048]
Definition: utf8.c:42
static const char * prefix[]
Definition: pcregrep.c:405
#define strcat(s, k)
static const char * str(char *buf, int n)
Definition: stats.c:84
const char * fname
Definition: ftaerr.cpp:27
const char * module
Definition: ftaerr.cpp:26
int line
Definition: ftaerr.cpp:28
string filename
Definition: ftaerr.cpp:55
FtaMsgModFiles * next
Definition: ftaerr.cpp:57
string modname
Definition: ftaerr.cpp:54
FtaMsgModTag * bmmt
Definition: ftaerr.cpp:56
FtaMsgModTagCtx * next
Definition: ftaerr.cpp:35
string strsubtag
Definition: ftaerr.cpp:32
string strtag
Definition: ftaerr.cpp:41
FtaMsgModTagCtx * bmctx
Definition: ftaerr.cpp:43
FtaMsgModTag * next
Definition: ftaerr.cpp:44
~FtaMsgModTag()
Definition: ftaerr.cpp:46
int inttag
Definition: ftaerr.cpp:42
FtaMsgModFiles * bmmf
Definition: ftaerr.cpp:86
string prefix_locus
Definition: ftaerr.cpp:72
FtaMsgPost()
Definition: ftaerr.cpp:88
bool show_msg_codes
Definition: ftaerr.cpp:77
bool show_msg_codeline
Definition: ftaerr.cpp:75
bool show_log_codeline
Definition: ftaerr.cpp:76
ErrSev msglevel
Definition: ftaerr.cpp:80
FILE * lfd
Definition: ftaerr.cpp:68
bool show_log_codes
Definition: ftaerr.cpp:78
ErrSev loglevel
Definition: ftaerr.cpp:83
bool hook_only
Definition: ftaerr.cpp:79
string logfile
Definition: ftaerr.cpp:69
virtual ~FtaMsgPost()
Definition: ftaerr.cpp:105
string prefix_feature
Definition: ftaerr.cpp:73
string prefix_accession
Definition: ftaerr.cpp:71
string appname
Definition: ftaerr.cpp:70
bool to_stderr
Definition: ftaerr.cpp:74
Definition: inftrees.h:24
Modified on Sat Dec 02 09:23:52 2023 by modify_doxy.py rev. 669887