XRootD
XrdSysTrace.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S y s T r a c e . h h */
4 /* */
5 /* (c) 2016 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <cstdio>
32 
33 #include "XrdSys/XrdSysFD.hh"
34 #include "XrdSys/XrdSysLogger.hh"
35 #include "XrdSys/XrdSysTrace.hh"
36 
37 /******************************************************************************/
38 /* C o n v e r s i o n F u n c t i o n s */
39 /******************************************************************************/
40 
41 namespace
42 {
44 
45 void ToMsgCB(int iovcnt, struct iovec *iov)
46 {
47  std::string msg;
48  int n = 0;
49 
50  for (int i = 2; i < iovcnt; i++) n += iov[i].iov_len;
51 
52  msg.reserve(n+1);
53 
54  for (int i = 2; i < iovcnt; i++)
55  msg.append((const char *)iov[i].iov_base, iov[i].iov_len);
56 
57  msgCB((const char *)iov[1].iov_base, msg.c_str(), true);
58 }
59 }
60 
61 /******************************************************************************/
62 /* S e t L o g g e r */
63 /******************************************************************************/
64 
65 void XrdSysTrace::SetLogger(XrdSysLogger *logp) {logP = logp;}
66 
67 void XrdSysTrace::SetLogger(msgCB_t cbP) {msgCB = cbP;}
68 
69 /******************************************************************************/
70 /* B e g */
71 /******************************************************************************/
72 
73 XrdSysTrace& XrdSysTrace::Beg(const char *usr,
74  const char *epn,
75  const char *txt)
76 {
77  char fmt[16];
78  const char *fmt1, *fmt2, *fmt3;
79  int n;
80 
81 // Generate prefix format (way too complicated)
82 //
83  if (usr) fmt1 = "%s ";
84  else {usr = "", fmt1 = "%s";}
85  if (epn) fmt2 = "%s_%s: ";
86  else {epn = ""; fmt2 = "%s%s: ";}
87  if (txt) fmt3 = "%s";
88  else {txt = ""; fmt3 = "";}
89  sprintf(fmt, "%s%s%s", fmt1, fmt2, fmt3);
90 
91 // Format the header
92 //
93  myMutex.Lock();
94  n = snprintf(pBuff, sizeof(pBuff), fmt, usr, iName, epn, txt);
95  if (n >= (int)sizeof(pBuff)) n = sizeof(pBuff)-1;
96 
97 // Start the trace procedure
98 //
99  ioVec[0].iov_base = 0; ioVec[0].iov_len = 0;
100  ioVec[1].iov_base = pBuff; ioVec[1].iov_len = n;
101 
102 // Reset ourselves
103 //
104  dPnt = 0;
105  dFree = txtMax;
106  vPnt = 2;
107 
108 // All done
109 //
110  return *this;
111 }
112 
113 /******************************************************************************/
114 /* E n d */
115 /******************************************************************************/
116 
118 {
119  (void)val;
120 
121 // Make sure an endline character appears
122 //
123  if (vPnt >= iovMax) vPnt = iovMax-1;
124  ioVec[vPnt] .iov_base = (char *)"\n";
125  ioVec[vPnt++].iov_len = 1;
126 
127 // Output the line
128 //
129  if (logP) logP->Put(vPnt, ioVec);
130  else if (msgCB) ToMsgCB(vPnt, ioVec);
131  else {static XrdSysLogger tLog(XrdSysFD_Dup(STDERR_FILENO), 0);
132  tLog.Put(vPnt, ioVec);
133  }
134 
135 // All done
136 //
137  myMutex.UnLock();
138  return *this;
139 }
140 
141 /******************************************************************************/
142 /* < < b o o l */
143 /******************************************************************************/
144 
146 {
147 
148 // If we have enough space then format the value
149 //
150  if (vPnt < iovMax)
151  {if (val)
152  {ioVec[vPnt] .iov_base = (char *)"True";
153  ioVec[vPnt++].iov_len = 4;
154  } else {
155  ioVec[vPnt] .iov_base = (char *)"False";
156  ioVec[vPnt++].iov_len = 5;
157  }
158  }
159  return *this;
160 }
161 
162 /******************************************************************************/
163 /* < < c h a r */
164 /******************************************************************************/
165 
167 {
168  static char hv[] = "0123456789abcdef";
169 
170 // If we have enough space then format the value
171 //
172  if (vPnt < iovMax && dFree > 1)
173  {if (doFmt)
174  {if (doFmt & Xrd::hex)
175  {ioVec[vPnt].iov_base = (char *)(&dBuff[dPnt]);
176  if (doFmt & Xrd::hex)
177  {ioVec[vPnt++].iov_len = 2;
178  dBuff[dPnt++] = hv[(val >> 4) & 0x0f];
179  dBuff[dPnt++] = hv[ val & 0xf0];
180  dFree -= 2;
181  } else if (doFmt & Xrd::oct && dFree > 2) {
182  ioVec[vPnt++].iov_len = 3;
183  dBuff[dPnt+2] = hv[val & 0x07]; val >>= 3;
184  dBuff[dPnt+1] = hv[val & 0x07]; val >>= 3;
185  dBuff[dPnt+1] = hv[val & 0x03];
186  dPnt += 3;
187  dFree -= 3;
188  }
189  }
190  if (doFmt & doOne) doFmt = Xrd::dec;
191  } else {
192  ioVec[vPnt] .iov_base = (char *)(&dBuff[dPnt]);
193  ioVec[vPnt++].iov_len = 1;
194  dBuff[dPnt++] = val; dFree--;
195  }
196  }
197  return *this;
198 }
199 
200 /******************************************************************************/
201 /* < < c o n s t c h a r * */
202 /******************************************************************************/
203 
205 {
206 
207 // If we have enough space then format the value
208 //
209  if (vPnt < iovMax)
210  {ioVec[vPnt] .iov_base = (char *)val;
211  ioVec[vPnt++].iov_len = strlen(val);
212  }
213  return *this;
214 }
215 
216 
217 /******************************************************************************/
218 /* < < std::string */
219 /******************************************************************************/
220 XrdSysTrace& XrdSysTrace::operator<<(const std::string& val)
221 {
222  return (*this << val.c_str());
223 }
224 
225 /******************************************************************************/
226 /* < < s h o r t */
227 /******************************************************************************/
228 
230 {
231  static const int xSz = sizeof("-32768");
232 
233 // If we have enough space then format the value
234 //
235  if (dFree >= xSz && vPnt < iovMax)
236  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%hx" : "%ho") : "%hd");
237  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
238  if (n > dFree) dFree = 0;
239  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
240  ioVec[vPnt++].iov_len = n;
241  dPnt += n; dFree -= n;
242  }
243  }
244  if (doFmt & doOne) doFmt = Xrd::dec;
245  return *this;
246 }
247 
248 /******************************************************************************/
249 /* < < i n t */
250 /******************************************************************************/
251 
253 {
254  static const int xSz = sizeof("-2147483648");
255 
256 // If we have enough space then format the value
257 //
258  if (dFree >= xSz && vPnt < iovMax)
259  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%x" : "%o") : "%d");
260  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
261  if (n > dFree) dFree = 0;
262  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
263  ioVec[vPnt++].iov_len = n;
264  dPnt += n; dFree -= n;
265  }
266  }
267  if (doFmt & doOne) doFmt = Xrd::dec;
268  return *this;
269 }
270 
271 /******************************************************************************/
272 /* < < l o n g */
273 /******************************************************************************/
274 
276 {
277 
278 // Fan out based on length of a long
279 //
280  if (sizeof(long) > 4) return *this<<static_cast<long long>(val);
281  else return *this<<static_cast<int>(val);
282 }
283 
284 /******************************************************************************/
285 /* < < l o n g l o n g */
286 /******************************************************************************/
287 
289 {
290  static const int xSz = sizeof("-9223372036854775808");
291 
292 // If we have enough space then format the value
293 //
294  if (dFree >= xSz && vPnt < iovMax)
295  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%llx" : "%llo") : "%lld");
296  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
297  if (n > dFree) dFree = 0;
298  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
299  ioVec[vPnt++].iov_len = n;
300  dPnt += n; dFree -= n;
301  }
302  }
303  if (doFmt & doOne) doFmt = Xrd::dec;
304  return *this;
305 }
306 
307 /******************************************************************************/
308 /* < < u n s i g n e d s h o r t */
309 /******************************************************************************/
310 
312 {
313  static const int xSz = sizeof("65535");
314 
315 // If we have enough space then format the value
316 //
317  if (dFree >= xSz && vPnt < iovMax)
318  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%hx" : "%ho") : "%hu");
319  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
320  if (n > dFree) dFree = 0;
321  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
322  ioVec[vPnt++].iov_len = n;
323  dPnt += n; dFree -= n;
324  }
325  }
326  if (doFmt & doOne) doFmt = Xrd::dec;
327  return *this;
328 }
329 
330 /******************************************************************************/
331 /* < < u n s i g n e d i n t */
332 /******************************************************************************/
333 
335 {
336  static const int xSz = sizeof("4294967295");
337 
338 // If we have enough space then format the value
339 //
340  if (dFree >= xSz && vPnt < iovMax)
341  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%x" : "%o") : "%u");
342  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
343  if (n > dFree) dFree = 0;
344  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
345  ioVec[vPnt++].iov_len = n;
346  dPnt += n; dFree -= n;
347  }
348  }
349  if (doFmt & doOne) doFmt = Xrd::dec;
350  return *this;
351 }
352 
353 /******************************************************************************/
354 /* < < u n s i g n e d l o n g */
355 /******************************************************************************/
356 
358 {
359 
360 // Fan out based on length of a long
361 //
362  if (sizeof(long) > 4) return *this<<static_cast<unsigned long long>(val);
363  else return *this<<static_cast<unsigned int>(val);
364 }
365 
366 /******************************************************************************/
367 /* < < u n s i g n e d l o n g l o n g */
368 /******************************************************************************/
369 
370 XrdSysTrace& XrdSysTrace::operator<<(unsigned long long val)
371 {
372  static const int xSz = sizeof("18446744073709551615");
373 
374 // If we have enough space then format the value
375 //
376  if (dFree >= xSz && vPnt < iovMax)
377  {const char *fmt = (doFmt ? (doFmt & Xrd::hex ? "%llx" : "%llo") : "%llu");
378  int n = snprintf(&dBuff[dPnt], dFree, fmt, val);
379  if (n > dFree) dFree = 0;
380  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
381  ioVec[vPnt++].iov_len = n;
382  dPnt += n; dFree -= n;
383  }
384  }
385  if (doFmt & doOne) doFmt = Xrd::dec;
386  return *this;
387 }
388 
389 /******************************************************************************/
390 /* < < v o i d * */
391 /******************************************************************************/
392 
394 {
395  static const int xSz = sizeof(void *)*2+1;
396 
397 // If we have enough space then format the value
398 //
399  if (dFree >= xSz && vPnt < iovMax)
400  {int n = snprintf(&dBuff[dPnt], dFree, "%p", val);
401  if (n > dFree) dFree = 0;
402  else {ioVec[vPnt] .iov_base = &dBuff[dPnt];
403  ioVec[vPnt++].iov_len = n;
404  dPnt += n; dFree -= n;
405  }
406  }
407  return *this;
408 }
409 
410 /******************************************************************************/
411 /* < < l o n g d o u b l e */
412 /******************************************************************************/
413 
414 XrdSysTrace& XrdSysTrace::Insert(long double val)
415 {
416  char tmp[32];
417  int n;
418 
419 // Gaurd against iovec overflows
420 //
421 if (vPnt < iovMax)
422  {
423 
424 // Convert the value into the temporary buffer
425 //
426  n = snprintf(tmp, sizeof(tmp), "%Lg", val);
427 
428 // If we have enough space then format the value
429 //
430  if (dFree > n && n < (int)sizeof(tmp))
431  {ioVec[vPnt] .iov_base = &dBuff[dPnt];
432  ioVec[vPnt++].iov_len = n;
433  strcpy(&dBuff[dPnt], tmp);
434  dPnt += n; dFree -= n;
435  }
436  }
437  return *this;
438 }
void Put(int iovcnt, struct iovec *iov)
XrdSysTrace & Beg(const char *usr=0, const char *epn=0, const char *txt=0)
Definition: XrdSysTrace.cc:73
void(* msgCB_t)(const char *tid, const char *msg, bool dbgmsg)
Definition: XrdSysTrace.hh:58
XrdSysTrace & operator<<(bool val)
Definition: XrdSysTrace.cc:145
void SetLogger(XrdSysLogger *logp)
Definition: XrdSysTrace.cc:65
XrdSsiLogger::MCB_t * msgCB
Definition: XrdSsiLogger.cc:59
@ oct
Definition: XrdSysTrace.hh:42
@ dec
Definition: XrdSysTrace.hh:42
@ hex
Definition: XrdSysTrace.hh:42