Line data Source code
1 : /* This file (traceln.h) was created by Ron Rechenmacher <ron@fnal.gov> on
2 : // Apr 18, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3 : // or COPYING file. If you do not have such a file, one can be obtained by
4 : // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5 : // $RCSfile: traceln.hh,v $
6 : // rev="$Revision: 1056 $$Date: 2019-02-25 15:57:13 -0600 (Mon, 25 Feb 2019) $";
7 : */
8 : /**
9 : * \file traceln.h
10 : * Defines TRACE macros which send "slow" traces to cout with line numbers
11 : *
12 : */
13 : #ifndef TRACE_INCLUDE_TRACE_TRACELN_H_
14 : #define TRACE_INCLUDE_TRACE_TRACELN_H_
15 :
16 : #ifdef __cplusplus
17 :
18 : // Use this define! -- trace.h won't define it's own version of TRACE_LOG_FUNCTION
19 : // The TRACE macro will then use the static vlntrace_user function defined in this file
20 : // for the "slow" tracing function (if appropriate mask bit is set :)
21 : # include <stdint.h> // uint16_t
22 : # include <string> // std::string
23 :
24 : // NOLINTBEGIN
25 : # define TRACE_LOG_FUN_PROTO \
26 : static void lntrace_user(struct timeval *, int, uint8_t, const char *, const char *, int, const char *, uint16_t nargs, \
27 : const char *msg, ...); \
28 : static void lntrace_user(struct timeval *, int, uint8_t, const char *, const char *, int, const char *, uint16_t nargs, \
29 : const std::string &msg, ...)
30 : // NOLINTEND
31 : # define TRACE_LOG_FUNCTION lntrace_user
32 : # include "TRACE/trace.h" // TRACE // NOLINT
33 :
34 : # if defined(__has_feature)
35 : # if __has_feature(thread_sanitizer)
36 : __attribute__((no_sanitize("thread")))
37 : # endif
38 : # endif
39 : static void
40 0 : vlntrace_user(struct timeval *tvp, int TID __attribute__((__unused__)), uint8_t lvl, const char *insert, const char *file, int line,
41 : const char *function __attribute__((__unused__)), uint16_t nargs, const char *msg, va_list ap)
42 : {
43 : /* I format output in a local output buffer (with specific/limited size)
44 : first. There are 2 main reasons that this is done:
45 : 1) allows the use of write to a specific tracePrintFd;
46 : 2) there will be one system call which is most efficient and less likely
47 : to have the output mangled in a multi-threaded environment.
48 : */
49 0 : char obuf[TRACE_USER_MSGMAX];
50 0 : char tbuf[0x100];
51 0 : size_t printed= 0;
52 0 : char *cp;
53 0 : struct tm tm_s;
54 0 : ssize_t quiet_warn= 0;
55 0 : if (traceTimeFmt == NULL) { // NOLINT
56 : // no matter who writes, it should basically be the same thing
57 0 : if ((cp= getenv("TRACE_TIME_FMT")) != NULL) { // NOLINT
58 0 : traceTimeFmt= cp; // single write here
59 : } else {
60 0 : traceTimeFmt= TRACE_DFLT_TIME_FMT; // OR single write here
61 : }
62 : }
63 0 : if (tvp->tv_sec == 0) { TRACE_GETTIMEOFDAY(tvp); }
64 : # if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))
65 : # pragma GCC diagnostic push
66 : # pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
67 : # endif
68 0 : localtime_r((time_t *)&tvp->tv_sec, &tm_s); // NOLINT
69 : # if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L))
70 : # pragma GCC diagnostic pop
71 : # endif
72 0 : strftime(tbuf, sizeof(tbuf), traceTimeFmt, &tm_s);
73 0 : printed= snprintf(obuf, sizeof(obuf), tbuf, (int)tvp->tv_usec); // possibly (probably) add usecs // NOLINT
74 :
75 : # define __SHORTFILE__ (strstr(&file[0], "/srcs/") ? strstr(&file[0], "/srcs/") + 6 : file)
76 :
77 0 : printed+= snprintf(&(obuf[printed]), sizeof(obuf) - printed,
78 0 : &(" %s %s:%d %s")[printed == 0 ? 1 : 0] // skip leading " " if nothing was printed (TRACE_TIME_FMT="")
79 : ,
80 0 : trace_lvlstrs[0][lvl & TLVLBITSMSK], __SHORTFILE__, line, insert);
81 :
82 0 : if (nargs) {
83 0 : printed+= vsnprintf(&(obuf[printed]), (printed < (int)sizeof(obuf)) ? sizeof(obuf) - printed : 0, msg, ap); // NOLINT
84 : } else {
85 : /* don't do any parsing for format specifiers in the msg -- tshow will
86 : also know to do this on the memory side of things */
87 0 : printed+= snprintf(&(obuf[printed]), (printed < (int)sizeof(obuf)) ? sizeof(obuf) - printed : 0, "%s", msg); // NOLINT
88 : }
89 :
90 : /* why not use writev??? B/c when writing to stdout, only each individual
91 : vector (not the whole array of vectors) is atomic/thread safe */
92 0 : if (printed < (int)sizeof(obuf)) { // NOLINT
93 : // there is room for the \n
94 : // buf first see if it is needed
95 0 : if (obuf[printed - 1] != '\n') {
96 : // NOLINTNEXTLINE(runtime/increment_decrement)
97 0 : obuf[printed++]= '\n'; // overwriting \0 is OK as we will specify the amount to write
98 : //printf("added \\n printed=%d\n",printed);
99 : }
100 : //else printf("already there printed=%d\n",printed);
101 0 : quiet_warn+= write(tracePrintFd[lvl & TLVLBITSMSK], obuf, printed);
102 : } else {
103 : // obuf[sizeof(obuf)-1] has '\0'. see if we should change it to \n
104 0 : if (obuf[sizeof(obuf) - 2] == '\n') {
105 0 : quiet_warn+= write(tracePrintFd[lvl & TLVLBITSMSK], obuf, sizeof(obuf) - 1);
106 : } else {
107 0 : obuf[sizeof(obuf) - 1]= '\n';
108 0 : quiet_warn+= write(tracePrintFd[lvl & TLVLBITSMSK], obuf, sizeof(obuf));
109 : //printf("changed \\0 to \\n printed=%d\n",);
110 : }
111 : }
112 0 : if (quiet_warn == -1) { perror("writeTracePrintFd"); }
113 0 : }
114 :
115 : SUPPRESS_NOT_USED_WARN
116 0 : static void lntrace_user(struct timeval *tvp, int TID, uint8_t lvl, const char *insert, const char *file, int line,
117 : const char *function, uint16_t nargs, const char *msg, ...)
118 : {
119 0 : va_list ap;
120 0 : va_start(ap, msg);
121 0 : vlntrace_user(tvp, TID, lvl, insert, file, line, function, nargs, msg, ap);
122 0 : va_end(ap);
123 0 : }
124 :
125 : # if (__GNUC__ >= 6) || (__cplusplus >= 201103L)
126 : # pragma GCC diagnostic push
127 : # pragma GCC diagnostic ignored "-Wvarargs"
128 : # endif
129 : SUPPRESS_NOT_USED_WARN
130 : static void lntrace_user(struct timeval *tvp, int TID, uint8_t lvl, const char *insert, const char *file, int line,
131 : const char *function, uint16_t nargs, const std::string &msg, ...)
132 : {
133 : va_list ap;
134 : va_start(ap, msg);
135 : vlntrace_user(tvp, TID, lvl, insert, file, line, function, nargs, &msg[0], ap);
136 : va_end(ap);
137 : } // trace
138 : # if (__GNUC__ >= 6) || (__cplusplus >= 201103L)
139 : # pragma GCC diagnostic pop
140 : # endif
141 :
142 : #endif // __cplusplus
143 : #endif // TRACE_INCLUDE_TRACE_TRACELN_H_
|