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;
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 ErrSev FtaStrSevToIntSev(const string& strsevcode)
125 {
126  if (strsevcode.empty())
127  return ErrSev(-1);
128 
129  static const map<string, ErrSev> sStringToInt = {
130  { "SEV_INFO", SEV_INFO },
131  { "SEV_WARNING", SEV_WARNING },
132  { "SEV_ERROR", SEV_ERROR },
133  { "SEV_REJECT", SEV_REJECT },
134  { "SEV_FATAL", SEV_FATAL }
135  };
136 
137  if (auto it = sStringToInt.find(strsevcode);
138  it != sStringToInt.end()) {
139  return it->second;
140  }
141 
142  return ErrSev(-1);
143 }
144 
145 /**********************************************************/
146 static void FtaErrGetMsgCodes(
147  const char* module, int code, int subcode, string& strcode, string& strsubcode, ErrSev& sevcode)
148 {
149  FtaMsgModTagCtx* bmctxp;
150  FtaMsgModFiles* bmmfp;
151  FtaMsgModTag* bmmtp;
152  FILE* fd;
153 
154  char* p;
155  char* q;
156  char s[2048];
157  char ch;
158  bool got_mod;
159 
160  if (! bmp)
161  FtaErrInit();
162 
163  for (got_mod = false, bmmfp = bmp->bmmf; bmmfp; bmmfp = bmmfp->next) {
164  if (bmmfp->modname != module) {
165  continue;
166  }
167 
168  got_mod = true;
169  for (bmmtp = bmmfp->bmmt; bmmtp; bmmtp = bmmtp->next) {
170  if (bmmtp->inttag != code)
171  continue;
172 
173  strcode = bmmtp->strtag;
174  for (bmctxp = bmmtp->bmctx; bmctxp; bmctxp = bmctxp->next) {
175  if (bmctxp->intsubtag != subcode)
176  continue;
177 
178  strsubcode = bmctxp->strsubtag;
179  sevcode = bmctxp->intseverity;
180  break;
181  }
182  break;
183  }
184  break;
185  }
186 
187  if (got_mod)
188  return;
189 
190  string curdir = CDir::GetCwd();
191  string buf = curdir + CDir::GetPathSeparator() + module + ".msg";
192  fd = fopen(buf.c_str(), "r");
193  if (! fd) {
194  buf = string(MESSAGE_DIR) + CDir::GetPathSeparator() + module + ".msg";
195  fd = fopen(buf.c_str(), "r");
196  if (! fd) {
197  return;
198  }
199  }
200 
201  bmmfp = new FtaMsgModFiles;
202  bmmfp->modname = module;
203  bmmfp->filename = buf;
204 
205  if (bmp->bmmf)
206  bmmfp->next = bmp->bmmf;
207  bmp->bmmf = bmmfp;
208 
209  bmmtp = nullptr;
210  while (fgets(s, 2047, fd)) {
211  if (s[0] != '$' || (s[1] != '^' && s[1] != '$'))
212  continue;
213 
214  string val1;
215  string val3;
216  int val2{ 0 };
217 
218  for (p = s + 2; *p == ' ' || *p == '\t'; p++) {}
219  for (q = p; *p && *p != ','; p++) {}
220  if (*p != ',')
221  continue;
222 
223  *p = '\0';
224  val1 = q;
225 
226  for (*p++ = ','; *p == ' ' || *p == '\t'; p++) {}
227  for (q = p; *p >= '0' && *p <= '9'; p++) {}
228 
229  if (q == p) {
230  continue;
231  }
232 
233  ch = *p;
234  *p = '\0';
235  val2 = atoi(q);
236  *p = ch;
237 
238  if (val2 < 1) {
239  continue;
240  }
241 
242  if (s[1] == '^' && ch == ',') {
243  for (p++; *p == ' ' || *p == '\t'; p++) {}
244  for (q = p;
245  *p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ',';
246  p++) {}
247  if (p > q) {
248  ch = *p;
249  *p = '\0';
250  if (! strcmp(q, "SEV_INFO") || ! strcmp(q, "SEV_WARNING") ||
251  ! strcmp(q, "SEV_ERROR") || ! strcmp(q, "SEV_REJECT") ||
252  ! strcmp(q, "SEV_FATAL")) {
253  val3 = q;
254  }
255  *p = ch;
256  }
257  }
258 
259  if (s[1] == '$') {
260  bmmtp = new FtaMsgModTag;
261  if (bmmfp->bmmt)
262  bmmtp->next = bmmfp->bmmt;
263  bmmfp->bmmt = bmmtp;
264 
265  bmmtp->strtag = val1;
266  bmmtp->inttag = val2;
267  if (val2 == code && strcode.empty())
268  strcode = val1;
269 
270  continue;
271  }
272 
273  if (! bmmfp->bmmt || ! bmmtp) {
274  continue;
275  }
276 
277  bmctxp = new FtaMsgModTagCtx;
278  if (bmmtp->bmctx)
279  bmctxp->next = bmmtp->bmctx;
280  bmmtp->bmctx = bmctxp;
281 
282  bmctxp->strsubtag = val1;
283  bmctxp->intsubtag = val2;
284  bmctxp->intseverity = FtaStrSevToIntSev(val3);
285 
286  if (val2 == subcode && strsubcode.empty() && ! strcode.empty()) {
287  strsubcode = val1;
288  if (sevcode < 0)
289  sevcode = bmctxp->intseverity;
290  }
291  }
292 
293  fclose(fd);
294 }
295 
296 /**********************************************************/
298 {
299  if (bmp)
300  return;
301 
302  bmp.reset(new FtaMsgPost());
303  bmp->appname = CNcbiApplication::GetAppName();
304 
305  fec.module = nullptr;
306  fec.fname = nullptr;
307  bmp->hook_only = false;
308  fec.line = -1;
309 }
310 
311 /**********************************************************/
312 void FtaErrFini(void)
313 {
314  if (bmp) {
315  bmp.reset();
316  }
317 }
318 
319 
320 /**********************************************************/
321 void FtaInstallPrefix(int prefix, const char* name, const char* location)
322 {
323  if (! name || *name == '\0')
324  return;
325 
326  if ((prefix & PREFIX_ACCESSION) == PREFIX_ACCESSION) {
327  bmp->prefix_accession = name;
328  }
329  if ((prefix & PREFIX_LOCUS) == PREFIX_LOCUS) {
330  bmp->prefix_locus = name;
331  }
332  if ((prefix & PREFIX_FEATURE) == PREFIX_FEATURE) {
333  char tmp[160];
334  strcpy(tmp, "FEAT=");
335  strncat(tmp, name, 20);
336  tmp[24] = '\0';
337  strcat(tmp, "[");
338  strncat(tmp, location, 127);
339  tmp[152] = '\0';
340  strcat(tmp, "]");
341  bmp->prefix_feature = tmp;
342  }
343 }
344 
345 /**********************************************************/
346 void FtaDeletePrefix(int prefix)
347 {
348  if ((prefix & PREFIX_ACCESSION) == PREFIX_ACCESSION) {
349  bmp->prefix_accession.clear();
350  }
351  if ((prefix & PREFIX_LOCUS) == PREFIX_LOCUS) {
352  bmp->prefix_locus.clear();
353  }
354  if ((prefix & PREFIX_FEATURE) == PREFIX_FEATURE) {
355  bmp->prefix_feature.clear();
356  }
357 }
358 
359 /**********************************************************/
360 bool ErrSetLog(const char* logfile)
361 {
362  struct tm* tm;
363  time_t now;
364  int i;
365 
366  if (! logfile || ! *logfile)
367  return (false);
368 
369  if (! bmp)
370  FtaErrInit();
371 
372  if (bmp->logfile.empty()) {
373  bmp->logfile = logfile;
374  }
375 
376  if (! bmp->lfd && ! bmp->logfile.empty()) {
377  time(&now);
378  tm = localtime(&now);
379  i = tm->tm_hour % 12;
380  if (! i)
381  i = 12;
382 
383  bmp->lfd = fopen(bmp->logfile.c_str(), "a");
384  fprintf(bmp->lfd,
385  "\n========================[ %s %d, %d %2d:%02d %s ]========================\n",
386  months[tm->tm_mon],
387  tm->tm_mday,
388  tm->tm_year + 1900,
389  i,
390  tm->tm_min,
391  (tm->tm_hour >= 12) ? "PM" : "AM");
392  }
393 
394  return (true);
395 }
396 
397 /**********************************************************/
399 {
400  if (! bmp)
401  FtaErrInit();
402 
403  if ((flags & EO_MSG_CODES) == EO_MSG_CODES)
404  bmp->show_msg_codes = true;
405  if ((flags & EO_LOG_CODES) == EO_LOG_CODES)
406  bmp->show_log_codes = true;
408  bmp->show_msg_codeline = true;
410  bmp->show_log_codeline = true;
411 }
412 
413 /**********************************************************/
414 void ErrLogPrintStr(const char* str)
415 {
416  if (! str || str[0] == '\0')
417  return;
418 
419  if (! bmp)
420  FtaErrInit();
421 
422  fprintf(bmp->lfd, "%s", str);
423 }
424 
425 /**********************************************************/
427 {
428  ErrSev prev;
429 
430  if (! bmp)
431  FtaErrInit();
432 
433  prev = bmp->loglevel;
434  bmp->loglevel = sev;
435  return (prev);
436 }
437 
438 /**********************************************************/
440 {
441  ErrSev prev;
442 
443  if (! bmp)
444  FtaErrInit();
445 
446  prev = bmp->msglevel;
447  bmp->msglevel = sev;
448  return (prev);
449 }
450 
451 /**********************************************************/
452 void Nlm_ErrSetContext(const char* module, const char* fname, int line)
453 {
454  if (! bmp)
455  FtaErrInit();
456 
457  fec.module = module;
458  fec.fname = fname;
459  fec.line = line;
460 }
461 
462 /**********************************************************/
464 {
465  EDiagSev cxx_severity;
466 
467  switch (c_severity) {
468  case SEV_NONE:
469  cxx_severity = eDiag_Trace;
470  break;
471  case SEV_INFO:
472  cxx_severity = eDiag_Info;
473  break;
474  case SEV_WARNING:
475  cxx_severity = eDiag_Warning;
476  break;
477  case SEV_ERROR:
478  cxx_severity = eDiag_Error;
479  break;
480  case SEV_REJECT:
481  cxx_severity = eDiag_Critical;
482  break;
483  case SEV_FATAL:
484  default:
485  cxx_severity = eDiag_Fatal;
486  break;
487  }
488  return (cxx_severity);
489 }
490 
491 /**********************************************************/
492 string ErrFormat(const char* fmt, ...)
493 {
494  va_list args;
495  char fpiBuffer[1024];
496  va_start(args, fmt);
497  vsnprintf(fpiBuffer, 1024, fmt, args);
498  va_end(args);
499  return fpiBuffer;
500 }
501 
502 /**********************************************************/
503 static void s_ReportError(ErrSev sev, int lev1, int lev2, string_view msg)
504 {
505  ErrSev fpiSevcode = ErrSev(-1);
506  int fpiIntcode = lev1;
507  int fpiIntsubcode = lev2;
508 
509  string fpiStrcode;
510  string fpiStrsubcode;
511 
512  int fpiLine = fec.line;
513  const char* fpiFname = fec.fname;
514  const char* fpiModule = fec.module;
515 
516  fec.module = nullptr;
517  fec.fname = nullptr;
518  fec.line = -1;
519 
520  if (fpiModule && *fpiModule)
521  FtaErrGetMsgCodes(fpiModule, fpiIntcode, fpiIntsubcode, fpiStrcode, fpiStrsubcode, fpiSevcode);
522  else
523  fpiModule = nullptr;
524 
525  if (fpiSevcode < SEV_NONE)
526  fpiSevcode = sev;
527 
528  if (bmp->appname.empty())
529  bmp->appname = CNcbiApplication::GetAppName();
530 
531  stringstream textStream;
532  if (! fpiStrcode.empty()) {
533  textStream << "[" << fpiStrcode.c_str();
534  if (! fpiStrsubcode.empty()) {
535  textStream << "." << fpiStrsubcode.c_str();
536  }
537  textStream << "] ";
538  }
539 
540  if (bmp->show_log_codeline) {
541  textStream << "{" << fpiFname << ", line " << fpiLine;
542  }
543  if (! bmp->prefix_locus.empty()) {
544  textStream << bmp->prefix_locus << ": ";
545  }
546  if (! bmp->prefix_accession.empty()) {
547  textStream << bmp->prefix_accession << ": ";
548  }
549  if (! bmp->prefix_feature.empty()) {
550  textStream << bmp->prefix_feature << " ";
551  }
552  textStream << msg;
553 
554  static const map<ErrSev, EDiagSev> sSeverityMap = {
555  { SEV_NONE, eDiag_Trace },
556  { SEV_INFO, eDiag_Info },
558  { SEV_ERROR, eDiag_Error },
561  };
562 
564  .Report(fpiModule ? fpiModule : "",
565  sSeverityMap.at(fpiSevcode),
566  lev1,
567  lev2,
568  textStream.str());
569 }
570 
571 /**********************************************************/
572 void Nlm_ErrPostEx(ErrSev sev, int lev1, int lev2, const char* fmt, ...)
573 {
574  if (! bmp)
575  FtaErrInit();
576 
577  if (! fec.fname || fec.line < 0) {
578  fec.module = nullptr;
579  fec.fname = nullptr;
580  fec.line = -1;
581  return;
582  }
583 
584  va_list args;
585  char fpiBuffer[1024];
586  va_start(args, fmt);
587  vsnprintf(fpiBuffer, 1024, fmt, args);
588  va_end(args);
589 
590  s_ReportError(sev, lev1, lev2, fpiBuffer);
591 }
592 
593 /**********************************************************/
594 void Nlm_ErrPostStr(ErrSev sev, int lev1, int lev2, string_view str)
595 {
596  if (! bmp)
597  FtaErrInit();
598 
599  if (! fec.fname || fec.line < 0) {
600  fec.module = nullptr;
601  fec.fname = nullptr;
602  fec.line = -1;
603  return;
604  }
605 
606  if (str.size() > 1024)
607  str = str.substr(0, 1024);
608  s_ReportError(sev, lev1, lev2, str);
609 }
610 
611 /**********************************************************/
612 
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
Definition: map.hpp:338
static uch flags
static ErrSev FtaStrSevToIntSev(const string &strsevcode)
Definition: ftaerr.cpp:124
USING_SCOPE(objects)
bool ErrSetLog(const char *logfile)
Definition: ftaerr.cpp:360
string ErrFormat(const char *fmt,...)
Definition: ftaerr.cpp:492
ErrSev ErrSetLogLevel(ErrSev sev)
Definition: ftaerr.cpp:426
void FtaDeletePrefix(int prefix)
Definition: ftaerr.cpp:346
void Nlm_ErrSetContext(const char *module, const char *fname, int line)
Definition: ftaerr.cpp:452
thread_local unique_ptr< FtaMsgPost > bmp
Definition: ftaerr.cpp:120
const char * months[]
Definition: ftaerr.cpp:118
void Nlm_ErrPostStr(ErrSev sev, int lev1, int lev2, string_view str)
Definition: ftaerr.cpp:594
FtaErrCode fec
Definition: ftaerr.cpp:121
void ErrSetOptFlags(int flags)
Definition: ftaerr.cpp:398
void FtaErrInit()
Definition: ftaerr.cpp:297
static void s_ReportError(ErrSev sev, int lev1, int lev2, string_view msg)
Definition: ftaerr.cpp:503
ErrSev ErrSetMessageLevel(ErrSev sev)
Definition: ftaerr.cpp:439
EDiagSev ErrCToCxxSeverity(int c_severity)
Definition: ftaerr.cpp:463
#define MESSAGE_DIR
Definition: ftaerr.cpp:19
void ErrLogPrintStr(const char *str)
Definition: ftaerr.cpp:414
void FtaErrFini(void)
Definition: ftaerr.cpp:312
static void FtaErrGetMsgCodes(const char *module, int code, int subcode, string &strcode, string &strsubcode, ErrSev &sevcode)
Definition: ftaerr.cpp:146
void Nlm_ErrPostEx(ErrSev sev, int lev1, int lev2, const char *fmt,...)
Definition: ftaerr.cpp:572
void FtaInstallPrefix(int prefix, const char *name, const char *location)
Definition: ftaerr.cpp:321
#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 strcat(s, k)
#define true
Definition: bool.h:35
#define false
Definition: bool.h:36
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static const char * str(char *buf, int n)
Definition: stats.c:84
static char tmp[3200]
Definition: utf8.c:42
static const char location[]
Definition: config.c:97
#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:1390
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
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 SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
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
ErrSev intseverity
Definition: ftaerr.cpp:34
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 Wed Sep 04 15:06:21 2024 by modify_doxy.py rev. 669887