XRootD
XrdXrootdMonitor.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d X r o o t d M o n i t o r . c c */
4 /* */
5 /* (c) 2004 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 <cerrno>
32 #include <cstdio>
33 #include <cstdlib>
34 #include <ctime>
35 #include <unistd.h>
36 #include <sys/types.h>
37 
38 #include "XrdVersion.hh"
39 
40 #include "XrdNet/XrdNetMsg.hh"
41 #include "XrdOuc/XrdOucEnv.hh"
42 #include "XrdOuc/XrdOucUtils.hh"
43 #include "XrdSys/XrdSysError.hh"
44 #include "XrdSys/XrdSysPlatform.hh"
45 
46 #include "Xrd/XrdScheduler.hh"
50 
51 /******************************************************************************/
52 /* S t a t i c A l l o c a t i o n */
53 /******************************************************************************/
54 
55 char *XrdXrootdMonitor::idRec = 0;
56 int XrdXrootdMonitor::idLen = 0;
57 char *XrdXrootdMonitor::Dest1 = 0;
58 int XrdXrootdMonitor::monMode1 = 0;
59 XrdNetMsg *XrdXrootdMonitor::InetDest1 = 0;
60 char *XrdXrootdMonitor::Dest2 = 0;
61 int XrdXrootdMonitor::monMode2 = 0;
62 XrdNetMsg *XrdXrootdMonitor::InetDest2 = 0;
64 XrdSysMutex XrdXrootdMonitor::windowMutex;
65 int XrdXrootdMonitor::monRlen = 0;
66 XrdXrootdMonitor::MonRdrBuff
67  XrdXrootdMonitor::rdrMon[XrdXrootdMonitor::rdrMax];
68 XrdXrootdMonitor::MonRdrBuff
69  *XrdXrootdMonitor::rdrMP = 0;
70 XrdSysMutex XrdXrootdMonitor::rdrMutex;
71 int XrdXrootdMonitor::monBlen = 0;
72 int XrdXrootdMonitor::lastEnt = 0;
73 int XrdXrootdMonitor::lastRnt = 0;
74 int XrdXrootdMonitor::isEnabled = 0;
75 int XrdXrootdMonitor::numMonitor = 0;
76 int XrdXrootdMonitor::autoFlash = 0;
77 int XrdXrootdMonitor::autoFlush = 600;
78 int XrdXrootdMonitor::FlushTime = 0;
79 int XrdXrootdMonitor::monIdent = 3600;
80 kXR_int32 XrdXrootdMonitor::currWindow = 0;
81 int XrdXrootdMonitor::rdrTOD = 0;
82 int XrdXrootdMonitor::rdrWin = 0;
83 int XrdXrootdMonitor::rdrNum = 3;
84 kXR_int32 XrdXrootdMonitor::sizeWindow = 60;
85 char XrdXrootdMonitor::monINFO = 0;
86 char XrdXrootdMonitor::monIO = 0;
87 char XrdXrootdMonitor::monFILE = 0;
88 char XrdXrootdMonitor::monREDR = 0;
89 char XrdXrootdMonitor::monUSER = 0;
90 char XrdXrootdMonitor::monAUTH = 0;
91 char XrdXrootdMonitor::monACTIVE = 0;
92 char XrdXrootdMonitor::monFSTAT = 0;
93 char XrdXrootdMonitor::monCLOCK = 0;
94 
95 /******************************************************************************/
96 /* G l o b a l s */
97 /******************************************************************************/
98 
100 
101 namespace XrdXrootdMonInfo
102 {
103 
104 inline static int32_t InitStartTime()
105 {
106  return htonl( time( 0 ) );
107 }
108 
109 XrdScheduler *Sched = 0;
110 XrdSysError *eDest = 0;
111 char *monHost = 0;
112 char *kySID = 0;
113 long long mySID = 0;
114 int32_t startTime = InitStartTime();
115 int kySIDSZ = 0;
117 
118 char *SidCGI[4] = {0};
119 int LidCGI[4] = {0};
120 char *SidJSON[4]= {0}; // 0:sidsite 1:sidhostid 2:sidinst 3:sidfull
121 int LidJSON[4]= {0};
122 }
123 
124 using namespace XrdXrootdMonInfo;
125 
126 /******************************************************************************/
127 /* L o c a l D e f i n e s */
128 /******************************************************************************/
129 
130 #define setTMark(TM_mb, TM_en, TM_tm) \
131  TM_mb->info[TM_en].arg0.val = mySID; \
132  TM_mb->info[TM_en].arg0.id[0] = XROOTD_MON_WINDOW; \
133  TM_mb->info[TM_en].arg1.Window = \
134  TM_mb->info[TM_en].arg2.Window = static_cast<kXR_int32>(ntohl(TM_tm));
135 
136 #define setTMurk(TM_mb, TM_en, TM_tm) \
137  TM_mb->info[TM_en].arg0.Window = rdrWin; \
138  TM_mb->info[TM_en].arg1.Window = static_cast<kXR_int32>(TM_tm);
139 
140 /******************************************************************************/
141 /* L o c a l C l a s s e s */
142 /******************************************************************************/
143 /******************************************************************************/
144 /* X r d X r o o t d M o n i t o r _ I d e n t */
145 /******************************************************************************/
146 
148 {
149 public:
150 
151 void DoIt() {
152  if (idInt >= 0)
153  {if (doIdnt) XrdXrootdMonitor::Ident();
154  if (doHail) doHail = XrdXrootdMonitor::Hello::Hail();
155  }
156  if ((doIdnt || doHail) && idInt > 0)
157  Sched->Schedule((XrdJob *)this, time(0)+idInt);
158  }
159 
160  XrdXrootdMonitor_Ident(int idt, bool ison) : XrdJob("monitor ident"),
161  idInt(idt), doIdnt(ison), doHail(true) {}
163 
164 private:
165 int idInt;
166 bool doIdnt;
167 bool doHail;
168 };
169 
170 /******************************************************************************/
171 /* C l a s s X r d X r o o t d M o n i t o r _ T i c k */
172 /******************************************************************************/
173 
175 {
176 public:
177 
178 void DoIt() {
179 #ifndef NODEBUG
180  const char *TraceID = "MonTick";
181 #endif
182  time_t Now = XrdXrootdMonitor::Tick();
183  if (Window && Now)
184  Sched->Schedule((XrdJob *)this, Now+Window);
185  else {TRACE(DEBUG, "Monitor clock stopping.");}
186  }
187 
188 void Set(XrdScheduler *sp, int intvl) {Sched = sp; Window = intvl;}
189 
190  XrdXrootdMonitor_Tick() : XrdJob("monitor window clock"),
191  Sched(0), Window(0) {}
193 
194 private:
195 XrdScheduler *Sched; // System scheduler
196 int Window;
197 };
198 
199 /******************************************************************************/
200 /* C l a s s X r d X r o o t d M o n i t o r L o c k */
201 /******************************************************************************/
202 
204 {
205 public:
206 
207 static void Lock() {monLock.Lock();}
208 
209 static void UnLock() {monLock.UnLock();}
210 
212  {if (theMonitor != XrdXrootdMonitor::altMon) unLock = 0;
213  else {unLock = 1; monLock.Lock();}
214  }
215  ~XrdXrootdMonitorLock() {if (unLock) monLock.UnLock();}
216 
217 private:
218 
219 static XrdSysMutex monLock;
220  char unLock;
221 };
222 
223 XrdSysMutex XrdXrootdMonitorLock::monLock;
224 
225 /******************************************************************************/
226 /* X r d X r o o t d M o n i t o r : : H e l l o */
227 /******************************************************************************/
228 
229 XrdXrootdMonitor::Hello::Hello(const char *dest, char mode)
230  : Next(0), theDest(0), theMode(0)
231 {
232  if (dest)
233  {Hello *nP = First;
234  while(nP) {if (!strcmp(dest, nP->theDest) && mode == theMode) return;
235  nP = nP->Next;
236  }
237  Next = First;
238  First = this;
239  theDest = strdup(dest);
240  theMode = mode;
241  }
242 }
243 
244 /******************************************************************************/
245 /* X r d X r o o t d M o n i t o r : : H e l l o : : H a i l */
246 /******************************************************************************/
247 
248 XrdXrootdMonitor::Hello *XrdXrootdMonitor::Hello::First = 0;
249 
251 {
252  Hello *nP = First;
253 
254 // Call all the registered ident methods
255 //
256  while(nP) {nP->Ident(); nP = nP->Next;}
257 
258 // Indicate whether or not anything would have been sent
259 //
260  return First != 0;
261 }
262 
263 /******************************************************************************/
264 /* X r d X r o o t d M o n i t o r : : U s e r : : D i s a b l e */
265 /******************************************************************************/
266 
268 {
269  if (Agent)
270  {XrdXrootdMonitor::unAlloc(Agent); Agent = 0;}
271  Fops = Iops = 0;
272 }
273 
274 /******************************************************************************/
275 /* X r d X r o o t d M o n i t o r : : U s e r : : E n a b l e */
276 /******************************************************************************/
277 
279 {
280  if (Agent || (Agent = XrdXrootdMonitor::Alloc(1)))
281  {Iops = XrdXrootdMonitor::monIO;
282  Fops = XrdXrootdMonitor::monFILE;
283  } else Iops = Fops = 0;
284 }
285 
286 /******************************************************************************/
287 /* X r d X r o o t d M o n i t o r : : U s e r : : R e g i s t e r */
288 /******************************************************************************/
289 
290 void XrdXrootdMonitor::User::Register(const char *Uname,
291  const char *Hname,
292  const char *Pname, unsigned int xSID)
293 {
294 #ifndef NODEBUG
295  const char *TraceID = "Monitor";
296 #endif
297  char *dotP, *colonP, *atP;
298  char uBuff[1024], tBuff[1024], sBuff[64];
299 
300 // Decode the user name as a.b:c@d and remap it for monitoring as
301 // <protocol>/a.{b|xSID}:<kySID>@host
302 //
303  snprintf(tBuff, sizeof(tBuff), "%s", Uname);
304  if ((dotP = index(tBuff, '.')) && (colonP = index(dotP+1, ':')) &&
305  (atP = index(colonP+1, '@')))
306  {*dotP = 0; *colonP = 0; *atP = 0;
307  if (xSID)
308  {snprintf(sBuff, sizeof(sBuff), " %u", xSID);
309  dotP = sBuff;
310  }
311 
312  int n = snprintf(uBuff, sizeof(uBuff), "%s/%s.%s:%s@%s", Pname, tBuff,
313  dotP+1, kySID, atP+1);
314 
315  if (n < 0 || n >= (int) sizeof(uBuff))
316  TRACE(LOGIN, "Login ID was truncated: " << uBuff);
317 
318  if (xSID) {TRACE(LOGIN,"Register remap "<<Uname<<" -> "<<uBuff);}
319  } else snprintf(uBuff, sizeof(uBuff), "%s/%s", Pname, Uname);
320 
321 // Generate a monitor identity for this user. We do not assign a dictioary
322 // identifier unless this entry is reported.
323 //
324  Agent = XrdXrootdMonitor::Alloc();
325  Did = 0;
326  Len = strlen(uBuff);
327  Name = strdup(uBuff);
328  Iops = XrdXrootdMonitor::monIO;
329  Fops = XrdXrootdMonitor::monFILE;
330 }
331 
332 /******************************************************************************/
333 /* R e p o r t */
334 /******************************************************************************/
335 
336 void XrdXrootdMonitor::User::Report(int eCode, int aCode)
337 {
338  char buff[1024];
339 
340  snprintf(buff, sizeof(buff), "&Uc=%d&Ec=%d&Ac=%d", ntohl(Did), eCode, aCode);
341 
342  XrdXrootdMonitor::Map(XROOTD_MON_MAPUEAC,*this,buff);
343 }
344 
345 /******************************************************************************/
346 
347 bool XrdXrootdMonitor::User::Report(WhatInfo infoT, const char *info)
348 {
349  char buff[4096];
350 
351 // Currently we support only the token external report
352 //
353  if (infoT != TokenInfo) return false;
354 
355  snprintf(buff, sizeof(buff), "&Uc=%d%s%s", ntohl(Did),
356  (*info == '&' ? "" : "&"), info);
357 
358  XrdXrootdMonitor::Map(XROOTD_MON_MAPTOKN,*this,buff);
359 
360  return true;
361 }
362 /******************************************************************************/
363 /* C o n s t r u c t o r */
364 /******************************************************************************/
365 
367 {
368  kXR_int32 localWindow;
369 
370 // Initialize last window to force a mark as well as the local window
371 //
372  lastWindow = 0;
373  localWindow = currWindow;
374 
375 // Allocate a monitor buffer
376 //
377  if (posix_memalign((void **)&monBuff, getpagesize(), monBlen))
378  eDest->Emsg("Monitor", "Unable to allocate monitor buffer.");
379  else {nextEnt = 1;
380  setTMark(monBuff, 0, localWindow);
381  }
382 }
383 
384 /******************************************************************************/
385 /* D e s t r u c t o r */
386 /******************************************************************************/
387 
388 XrdXrootdMonitor::~XrdXrootdMonitor()
389 {
390 // Release buffer
391  if (monBuff) {Flush(); free(monBuff);}
392 }
393 
394 /******************************************************************************/
395 /* a p p I D */
396 /******************************************************************************/
397 
399 {
400  static const int apInfoSize = sizeof(XrdXrootdMonTrace)-4;
401 
402 // Application ID's are only meaningful for io event recording
403 //
404  if (this == altMon || !*id) return;
405 
406 // Fill out the monitor record
407 //
408  if (lastWindow != currWindow) Mark();
409  else if (nextEnt == lastEnt) Flush();
410  monBuff->info[nextEnt].arg0.id[0] = XROOTD_MON_APPID;
411  strncpy((char *)(&(monBuff->info[nextEnt])+4), id, apInfoSize);
412 }
413 
414 /******************************************************************************/
415 /* A l l o c */
416 /******************************************************************************/
417 
418 XrdXrootdMonitor *XrdXrootdMonitor::Alloc(int force)
419 {
420  XrdXrootdMonitor *mp;
421  int lastVal;
422 
423 // If enabled, create a new object (if possible). If we are not monitoring
424 // i/o then return the global object.
425 //
426 // if (!isEnabled || (isEnabled < 0 && !force)) mp = 0;
427  if (!isEnabled) mp = 0;
428  else if (!monIO) mp = altMon;
429  else if ((mp = new XrdXrootdMonitor()))
430  if (!(mp->monBuff)) {delete mp; mp = 0;}
431 
432 // Check if we should turn on the monitor clock
433 //
434  if (mp && isEnabled < 0)
435  {windowMutex.Lock();
436  lastVal = numMonitor; numMonitor++;
437  if (!lastVal && !monREDR) startClock();
438  windowMutex.UnLock();
439  }
440 
441 // All done
442 //
443  return mp;
444 }
445 
446 /******************************************************************************/
447 /* C l o s e */
448 /******************************************************************************/
449 
450 void XrdXrootdMonitor::Close(kXR_unt32 dictid, long long rTot, long long wTot)
451 {
452  XrdXrootdMonitorLock mLock(this);
453  unsigned int rVal, wVal;
454 
455 // Fill out the monitor record (we allow the compiler to correctly cast data)
456 //
457  if (lastWindow != currWindow) Mark();
458  else if (nextEnt == lastEnt) Flush();
459  monBuff->info[nextEnt].arg0.id[0] = XROOTD_MON_CLOSE;
460  monBuff->info[nextEnt].arg0.id[1] = do_Shift(rTot, rVal);
461  monBuff->info[nextEnt].arg0.rTot[1] = htonl(rVal);
462  monBuff->info[nextEnt].arg0.id[2] = do_Shift(wTot, wVal);
463  monBuff->info[nextEnt].arg0.id[3] = 0;
464  monBuff->info[nextEnt].arg1.wTot = htonl(wVal);
465  monBuff->info[nextEnt++].arg2.dictid = dictid;
466 
467 // Check if we need to duplicate this entry
468 //
469  if (altMon && this != altMon) altMon->Dup(&monBuff->info[nextEnt-1]);
470 }
471 
472 /******************************************************************************/
473 /* D e f a u l t s */
474 /******************************************************************************/
475 
476 // This version must be called after the subsequent version!
477 
478 void XrdXrootdMonitor::Defaults(char *dest1, int mode1, char *dest2, int mode2)
479 {
480  int mmode;
481 
482 // If there are no destination then only g-stream events may be enabled.
483 // Otherwise, sort out the destinations relative to modes.
484 //
485  if (!dest1 && !dest2) {isEnabled = 0; return;}
486  if (!dest1) {dest1 = dest2; dest2 = 0; mode1 |= mode2; mode2 = 0;}
487 
488 // Set the default destinations (caller supplied strdup'd strings)
489 //
490  if (Dest1) free(Dest1);
491  Dest1 = dest1; monMode1 = mode1;
492  if (Dest2) free(Dest2);
493  Dest2 = dest2; monMode2 = mode2;
494 
495 // Set overall monitor mode
496 //
497  mmode = mode1 | mode2;
498  monACTIVE = (mmode ? 1 : 0);
499  isEnabled = (mmode & XROOTD_MON_ALL ? 1 :-1);
500  monIO = (mmode & XROOTD_MON_IO ? 1 : 0);
501  monIO = (mmode & XROOTD_MON_IOV ? 2 : monIO);
502  monINFO = (mmode & XROOTD_MON_INFO ? 1 : 0);
503  monFILE = (mmode & XROOTD_MON_FILE ? 1 : 0) | monIO;
504  monREDR = (mmode & XROOTD_MON_REDR ? 1 : 0);
505  monUSER = (mmode & XROOTD_MON_USER ? 1 : 0);
506  monAUTH = (mmode & XROOTD_MON_AUTH ? 1 : 0);
507  monFSTAT = (mmode & XROOTD_MON_FSTA && monFSTAT ? 1 : 0);
508 
509 // Compute whether or not we need the clock running
510 //
511  if (monREDR || (isEnabled > 0 && (monIO || monFILE))) monCLOCK = 1;
512 
513 // Check where user information should go
514 //
515  if (((mode1 & XROOTD_MON_IO) && (mode1 & XROOTD_MON_USER))
516  || ((mode2 & XROOTD_MON_IO) && (mode2 & XROOTD_MON_USER)))
517  {if ((!(mode1 & XROOTD_MON_IO) && (mode1 & XROOTD_MON_USER))
518  || (!(mode2 & XROOTD_MON_IO) && (mode2 & XROOTD_MON_USER))) monUSER = 3;
519  else monUSER = 2;
520  }
521 
522 // If we are monitoring redirections then set an envar saying how often idents
523 // should be sent (this also tips off other layers to handle such monitoring)
524 //
525  if (monREDR) XrdOucEnv::Export("XRDMONRDR", monIdent);
526 }
527 
528 /******************************************************************************/
529 
530 void XrdXrootdMonitor::Defaults(int msz, int rsz, int wsz,
531  int flush, int flash, int idt, int rnm,
532  int fbsz, int fsint, int fsopt, int fsion)
533 {
534 
535 // Set default window size and flush time
536 //
537  sizeWindow = (wsz <= 0 ? 60 : wsz);
538  autoFlush = (flush <= 0 ? 600 : flush);
539  autoFlash = (flash <= 0 ? 0 : flash);
540  monIdent = idt;
541  rdrNum = (rnm <= 0 || rnm > rdrMax ? 3 : rnm);
542  rdrWin = (sizeWindow > 16777215 ? 16777215 : sizeWindow);
543  rdrWin = htonl(rdrWin);
544 
545 // Set the fstat defaults
546 //
547  XrdXrootdMonFile::Defaults(fsint, fsopt, fsion, fbsz);
548  monFSTAT = fsint != 0;
549 
550 // Set default monitor buffer size
551 //
552  if (msz <= 0) msz = 16384;
553  else if (msz < 1024) msz = 1024;
554  else msz = msz/sizeof(XrdXrootdMonTrace)*sizeof(XrdXrootdMonTrace);
555  lastEnt = (msz-sizeof(XrdXrootdMonHeader))/sizeof(XrdXrootdMonTrace);
556  monBlen = (lastEnt*sizeof(XrdXrootdMonTrace))+sizeof(XrdXrootdMonHeader);
557  lastEnt--;
558 
559 // Set default monitor redirect buffer size
560 //
561  if (rsz <= 0) rsz = 32768;
562  else if (rsz < 2048) rsz = 2048;
563  lastRnt = (rsz-(sizeof(XrdXrootdMonHeader) + 16))/sizeof(XrdXrootdMonRedir);
564  monRlen = (lastRnt*sizeof(XrdXrootdMonRedir))+sizeof(XrdXrootdMonHeader)+16;
565  lastRnt--;
566 }
567 
568 /******************************************************************************/
569 /* D i s c */
570 /******************************************************************************/
571 
572 void XrdXrootdMonitor::Disc(kXR_unt32 dictid, int csec, char Flags)
573 {
574  XrdXrootdMonitorLock mLock(this);
575 
576 // Check if this should not be included in the io trace
577 //
578  if (this != altMon && monUSER == 1 && altMon)
579  {altMon->Disc(dictid, csec); return;}
580 
581 // Fill out the monitor record (let compiler cast the data correctly)
582 //
583  if (lastWindow != currWindow) Mark();
584  else if (nextEnt == lastEnt) Flush();
585  monBuff->info[nextEnt].arg0.rTot[0] = 0;
586  monBuff->info[nextEnt].arg0.id[0] = XROOTD_MON_DISC;
587  monBuff->info[nextEnt].arg0.id[1] = Flags;
588  monBuff->info[nextEnt].arg1.wTot = htonl(csec);
589  monBuff->info[nextEnt++].arg2.dictid = dictid;
590 
591 // Check if we need to duplicate this entry
592 //
593  if (altMon && this != altMon && monUSER == 3)
594  altMon->Dup(&monBuff->info[nextEnt-1]);
595 }
596 
597 /******************************************************************************/
598 /* D u p */
599 /******************************************************************************/
600 
601 void XrdXrootdMonitor::Dup(XrdXrootdMonTrace *mrec)
602 {
603  XrdXrootdMonitorLock mLock(this);
604 
605 // Fill out the monitor record
606 //
607  if (lastWindow != currWindow) Mark();
608  else if (nextEnt == lastEnt) Flush();
609  memcpy(&monBuff->info[nextEnt],(const void *)mrec,sizeof(XrdXrootdMonTrace));
610  nextEnt++;
611 }
612 
613 /******************************************************************************/
614 /* Private: F e t c h */
615 /******************************************************************************/
616 
617 XrdXrootdMonitor::MonRdrBuff *XrdXrootdMonitor::Fetch()
618 {
619  MonRdrBuff *bP;
620 
621 // Get the next available stream and promote another one
622 //
623  rdrMutex.Lock();
624  if ((bP = rdrMP)) rdrMP = rdrMP->Next;
625  rdrMutex.UnLock();
626  return bP;
627 }
628 
629 /******************************************************************************/
630 /* I n i t */
631 /******************************************************************************/
632 
634  const char *iHost, const char *iProg,
635  const char *iName, int Port)
636 {
637  const char *cgID0 = "&site=%s";
638  const char *cgID1 = "&host=%s";
639  const char *cgID2 = "&port=%d&inst=%s";
640  const char *cgID3 = "&pgm=%s&ver=%s";
641 
642  const char *jsID0 = "\"src\":{\"site\":\"%s\"}";
643  const char *jsID1 = "%s\"host\":\"%s\"}";
644  const char *jsID2 = "%s\"port\":%d,\"inst\":\"%s\"}";
645  const char *jsID3 = "%s\"pgm\":\"%s\",\"ver\":\"%s\"}";
646 
647  XrdXrootdMonMap *mP;
648  char iBuff[1024], iMuff[2048], iPuff[1024];
649  int n, i, j;
650 
651 // Set static variables
652 //
653  Sched = sp;
654  eDest = errp;
655 
656 // Generate our server ID (the version is not part of he fingerprint)
657 //
658  strcpy(iBuff, "=/");
659  kySID = XrdOucUtils::Ident(mySID, iBuff+2, sizeof(iBuff)-2,
660  iHost, iProg, iName, Port);
661  n = strlen(iBuff);
662  snprintf(iBuff+n, sizeof(iBuff)-n, "&ver=%s", XrdVERSION);
663 
664  kySIDSZ = strlen(kySID);
665  monHost = strdup(iHost);
666 
667 // Ignore array bounds warning from gcc 12 triggered because the allocated
668 // memory for the XrdXrootdMonMap is smaller than sizeof(XrdXrootdMonMap)
669 #if defined(__GNUC__) && __GNUC__ >= 12
670 #pragma GCC diagnostic push
671 #pragma GCC diagnostic ignored "-Warray-bounds"
672 #endif
673 // Create identification record
674 //
675  idLen = strlen(iBuff) + sizeof(XrdXrootdMonHeader) + sizeof(kXR_int32);
676  idRec = (char *)malloc(idLen+1);
677  mP = (XrdXrootdMonMap *)idRec;
678  fillHeader(&(mP->hdr), XROOTD_MON_MAPIDNT, idLen);
679  mP->hdr.pseq = 0;
680  mP->dictid = 0;
681  strcpy(mP->info, iBuff);
682 #if defined(__GNUC__) && __GNUC__ >= 12
683 #pragma GCC diagnostic pop
684 #endif
685 
686 // Generate a CGI version of all the variations
687 //
688  const char *Site (getenv("XRDSITE") ? getenv("XRDSITE") : "");
689  i = snprintf(iPuff, sizeof(iPuff), cgID0, Site);
690  SidCGI[0] = strdup(iPuff);
691  LidCGI[0] = strlen(iPuff);
692 
693  n = sizeof(iPuff)-i; j = i;
694  i = snprintf(iPuff+j, n, cgID1, iHost);
695  SidCGI[1] = strdup(iPuff);
696  LidCGI[1] = strlen(iPuff);
697 
698  n -= i; j += i;
699  i = snprintf(iPuff+j, n, cgID2, Port, iName);
700  SidCGI[2] = strdup(iPuff);
701  LidCGI[2] = strlen(iPuff);
702 
703  n -= i; j += i;
704  snprintf(iPuff+j, n, cgID3, iProg, XrdVERSION);
705  SidCGI[3] = strdup(iPuff);
706  LidCGI[3] = strlen(iPuff);
707 
708 // Generate a JSON version of all the variations.
709 //
710  n = snprintf(iPuff, sizeof(iPuff), jsID0, Site);
711  SidJSON[0] = strdup(iPuff);
712  LidJSON[0] = strlen(iPuff);
713 
714  strcpy(iPuff+n-1, ",");
715  n = snprintf(iMuff, sizeof(iMuff), jsID1, iPuff, iHost);
716  SidJSON[1] = strdup(iMuff);
717  LidJSON[1] = strlen(iMuff);
718 
719  strcpy(iMuff+n-1, ",");
720  n = snprintf(iPuff, sizeof(iPuff), jsID2, iMuff, Port, iName);
721  SidJSON[2] = strdup(iPuff);
722  LidJSON[2] = strlen(iPuff);
723 
724  strcpy(iPuff+n-1, ",");
725  snprintf(iMuff, sizeof(iMuff), jsID3, iPuff, iProg, XrdVERSION);
726  SidJSON[3] = strdup(iMuff);
727  LidJSON[3] = strlen(iMuff);
728 }
729 
730 /******************************************************************************/
731 
733 {
734  static XrdXrootdMonitor_Ident MonIdent(monIdent, isEnabled);
735  int i, Now = time(0);
736  bool aOK;
737 
738 // Setup the primary destination
739 //
740  if (Dest1)
741  {InetDest1 = new XrdNetMsg(eDest, Dest1, &aOK);
742  if (!aOK)
743  {eDest->Emsg("Monitor", "Unable to setup primary monitor collector.");
744  return 0;
745  }
746  }
747 
748 // Setup the secondary destination
749 //
750  if (Dest2)
751  {InetDest2 = new XrdNetMsg(eDest, Dest2, &aOK);
752  if (!aOK)
753  {eDest->Emsg("Monitor","Unable to setup secondary monitor collector.");
754  return 0;
755  }
756  }
757 
758 // Now schedule the first identification record
759 //
760  if (Sched && monIdent >= 0) Sched->Schedule((XrdJob *)&MonIdent);
761 
762 // There is nothing more to do unless we have been enabled via Defaults()
763 //
764  if (!isEnabled) return 1;
765 
766 // If there is a destination that is only collecting file events, then
767 // allocate a global monitor object but don't start the timer just yet.
768 //
769  if ((monMode1 && !(monMode1 & XROOTD_MON_IO))
770  || (monMode2 && !(monMode2 & XROOTD_MON_IO)))
771  if (!(altMon = new XrdXrootdMonitor()) || !altMon->monBuff)
772  {if (altMon) {delete altMon; altMon = 0;}
773  eDest->Emsg("Monitor","allocate monitor; insufficient storage.");
774  return 0;
775  }
776 
777 // Turn on the monitoring clock if we need it running all the time
778 //
779  if (monCLOCK) startClock();
780 
781 // If we are monitoring file stats then start that up
782 //
783  if (!Sched || !monFSTAT) monFSTAT = 0;
784  else if (!XrdXrootdMonFile::Init()) return 0;
785 
786 // If we are not monitoring redirections, we are done!
787 //
788  if (!monREDR) return 1;
789 
790 // Allocate as many redirection monitors as requested
791 //
792  for (i = 0; i < rdrNum; i++)
793  {if (posix_memalign((void **)&rdrMon[i].Buff, getpagesize(),monRlen))
794  {eDest->Emsg("Monitor", "Unable to allocate monitor rdr buffer.");
795  return 0;
796  }
797  rdrMon[i].Buff->sID = mySID;
798  rdrMon[i].Buff->sXX[0] = XROOTD_MON_REDSID;
799  rdrMon[i].Next = (i ? &rdrMon[i-1] : &rdrMon[0]);
800  rdrMon[i].nextEnt = 0;
801  rdrMon[i].flushIt = Now + autoFlush;
802  rdrMon[i].lastTOD = 0;
803  }
804  rdrMon[0].Next = &rdrMon[i-1];
805  rdrMP = &rdrMon[0];
806 
807 // All done
808 //
809  return 1;
810 }
811 
812 /******************************************************************************/
813 /* G e t D i c t I D */
814 /******************************************************************************/
815 
817 {
818  static XrdSysMutex seqMutex;
819  static unsigned int monSeqID = 1;
820  unsigned int mySeqID;
821 
822 // Assign a unique ID for this entry
823 //
824  seqMutex.Lock();
825  mySeqID = monSeqID++;
826  seqMutex.UnLock();
827 
828 // Return the ID
829 //
830  if (hbo) return mySeqID;
831  return htonl(mySeqID);
832 }
833 
834 /******************************************************************************/
835 /* Private: M a p */
836 /******************************************************************************/
837 
838 kXR_unt32 XrdXrootdMonitor::Map(char code, XrdXrootdMonitor::User &uInfo,
839  const char *path)
840 {
841  XrdXrootdMonMap map;
842  int size, montype;
843 
844 // Copy in the username and path
845 //
846  map.dictid = GetDictID();
847  strcpy(map.info, uInfo.Name);
848  size = uInfo.Len;
849  if (path)
850  {*(map.info+size) = '\n';
851  strlcpy(map.info+size+1, path, sizeof(map.info)-size-1);
852  size = size + strlen(path) + 1;
853  }
854 
855 // Fill in the header
856 //
857  size = sizeof(XrdXrootdMonHeader)+sizeof(kXR_int32)+size;
858  fillHeader(&map.hdr, code, size);
859 
860 // Route the packet to all destinations that need them
861 //
862  if (code == XROOTD_MON_MAPPATH) montype = XROOTD_MON_PATH;
863  else if (code == XROOTD_MON_MAPUSER
864  || code == XROOTD_MON_MAPTOKN
865  || code == XROOTD_MON_MAPUEAC) montype = XROOTD_MON_USER;
866  else montype = XROOTD_MON_INFO;
867  Send(montype, (void *)&map, size);
868 
869 // Return the dictionary id
870 //
871  return map.dictid;
872 }
873 
874 /******************************************************************************/
875 /* O p e n */
876 /******************************************************************************/
877 
878 void XrdXrootdMonitor::Open(kXR_unt32 dictid, off_t fsize)
879 {
880  XrdXrootdMonitorLock mLock(this);
881 
882  if (lastWindow != currWindow) Mark();
883  else if (nextEnt == lastEnt) Flush();
884  h2nll(fsize, monBuff->info[nextEnt].arg0.val);
885  monBuff->info[nextEnt].arg0.id[0] = XROOTD_MON_OPEN;
886  monBuff->info[nextEnt].arg1.buflen = 0;
887  monBuff->info[nextEnt++].arg2.dictid = dictid;
888 
889 // Check if we need to duplicate this entry
890 //
891  if (altMon && this != altMon) altMon->Dup(&monBuff->info[nextEnt-1]);
892 }
893 
894 /******************************************************************************/
895 /* R e d i r e c t */
896 /******************************************************************************/
897 
898 int XrdXrootdMonitor::Redirect(kXR_unt32 mID, const char *hName, int Port,
899  char opC, const char *Path)
900 {
901  XrdXrootdMonRedir *mtP;
902  MonRdrBuff *mP = Fetch();
903  int n, slots, hLen, pLen;
904  char *dest;
905 
906 // Take care of the server's name which might actually be a path
907 //
908  if (*hName == '/') {Path = hName; hName = ""; hLen = 0;}
909  else {const char *quest = index(hName, '?');
910  hLen = (quest ? quest - hName : strlen(hName));
911  if (hLen > 256) hLen = 256;
912  }
913 
914 // Take care of the path
915 //
916  pLen = strlen(Path);
917  if (pLen > 1024) pLen = 1024;
918 
919 // Compute number of entries needed here
920 //
921  n = (hLen + 1 + pLen + 1); // "<host>:<path>\0"
922  slots = n / sizeof(XrdXrootdMonRedir);
923  if (n % sizeof(XrdXrootdMonRedir)) slots++;
924  pLen = slots * sizeof(XrdXrootdMonRedir) - (hLen+1);
925 
926 // Obtain a lock on this buffer
927 //
928  if (!mP) return 0;
929  mP->Mutex.Lock();
930 
931 // If we don't have enough slots, flush this buffer. Note that we account for
932 // the ending timing mark here (an extra slot).
933 //
934  if (mP->nextEnt + slots + 2 >= lastRnt) Flush(mP);
935 
936 // Check if we need a timing mark
937 //
938  if (mP->lastTOD != rdrTOD)
939  {mP->lastTOD = rdrTOD;
940  setTMurk(mP->Buff, mP->nextEnt, mP->lastTOD);
941  mP->nextEnt++;
942  }
943 
944 // Fill out the buffer
945 //
946  mtP = &(mP->Buff->info[mP->nextEnt]);
947  mtP->arg0.rdr.Type = XROOTD_MON_REDIRECT | opC;
948  mtP->arg0.rdr.Dent = static_cast<char>(slots);
949  mtP->arg0.rdr.Port = htons(static_cast<short>(Port));
950  mtP->arg1.dictid = mID;
951  dest = (char *)(mtP+1);
952  strncpy(dest, hName,hLen); dest += hLen; *dest++ = ':';
953  strncpy(dest, Path, pLen);
954 
955 // Adjust pointer and return
956 //
957  mP->nextEnt = mP->nextEnt + (slots+1);
958  mP->Mutex.UnLock();
959  return 0;
960 }
961 
962 
963 /******************************************************************************/
964 /* T i c k */
965 /******************************************************************************/
966 
968 {
969  time_t Now = time(0);
970  int nextFlush;
971 
972 // We can safely set the window as we are the only ones doing so and memory
973 // access is atomic as long as it sits within a cache line (which it does).
974 //
975  currWindow = static_cast<kXR_int32>(Now);
976  rdrTOD = htonl(currWindow);
977  nextFlush = currWindow + autoFlush;
978 
979 // Check to see if we should flush the alternate monitor
980 //
981  if (altMon && currWindow >= FlushTime)
983  if (currWindow >= FlushTime)
984  {if (altMon->nextEnt > 1) altMon->Flush();
985  else FlushTime = nextFlush;
986  }
988  }
989 
990 // Now check to see if we need to flush redirect buffers
991 //
992  if (monREDR)
993  {int n = rdrNum;
994  while(n--)
995  {rdrMon[n].Mutex.Lock();
996  if (rdrMon[n].nextEnt == 0) rdrMon[n].flushIt = nextFlush;
997  else if (rdrMon[n].flushIt <= currWindow) Flush(&rdrMon[n]);
998  rdrMon[n].Mutex.UnLock();
999  }
1000  }
1001 
1002 // All done. Stop the clock if there is no reason for it to be running. The
1003 // clock always runs if we are monitoring redirects or all clients. Otherwise,
1004 // the clock only runs if we have a one or more client-specific monitors.
1005 //
1006  if (!monREDR && isEnabled < 0)
1007  {windowMutex.Lock();
1008  if (!numMonitor) Now = 0;
1009  windowMutex.UnLock();
1010  }
1011  return Now;
1012 }
1013 
1014 /******************************************************************************/
1015 /* u n A l l o c */
1016 /******************************************************************************/
1017 
1018 void XrdXrootdMonitor::unAlloc(XrdXrootdMonitor *monp)
1019 {
1020 
1021 // We must delete this object if we are de-allocating the local monitor.
1022 //
1023  if (monp != altMon) delete monp;
1024 
1025 // Decrease number being monitored if in selective mode
1026 //
1027  if (isEnabled < 0)
1028  {windowMutex.Lock();
1029  numMonitor--;
1030  windowMutex.UnLock();
1031  }
1032 }
1033 
1034 /******************************************************************************/
1035 /* P r i v a t e M e t h o d s */
1036 /******************************************************************************/
1037 /******************************************************************************/
1038 /* d o _ S h i f t */
1039 /******************************************************************************/
1040 
1041 unsigned char XrdXrootdMonitor::do_Shift(long long xTot, unsigned int &xVal)
1042 {
1043  const long long smask = 0x7fffffff00000000LL;
1044  const long long xmask = 0x7fffffffffffffffLL;
1045  unsigned char xshift = 0;
1046 
1047  xTot &= xmask;
1048  while(xTot & smask) {xTot = xTot >> 1LL; xshift++;}
1049  xVal = static_cast<unsigned int>(xTot);
1050 
1051  return xshift;
1052 }
1053 
1054 /******************************************************************************/
1055 /* f i l l H e a d e r */
1056 /******************************************************************************/
1057 
1058 void XrdXrootdMonitor::fillHeader(XrdXrootdMonHeader *hdr,
1059  const char id, int size)
1060 {
1061 
1062 // Fill in the header
1063 //
1064  hdr->code = static_cast<kXR_char>(id);
1065 // hdr->pseq = static_cast<kXR_char>(myseq); // Filled in Send()
1066  hdr->plen = htons(static_cast<uint16_t>(size));
1067  hdr->stod = startTime;
1068 }
1069 
1070 /******************************************************************************/
1071 /* F l u s h */
1072 /******************************************************************************/
1073 
1074 void XrdXrootdMonitor::Flush()
1075 {
1076  int size;
1077  kXR_int32 localWindow, now;
1078 
1079 // Do not flush if the buffer is empty
1080 //
1081  if (nextEnt <= 1) return;
1082 
1083 // Get the current window marker. No need for locks as simple memory accesses
1084 // are sufficiently synchrnozed for our purposes.
1085 //
1086  localWindow = currWindow;
1087 
1088 // Fill in the header and in the process we will have the current time
1089 //
1090  size = (nextEnt+1)*sizeof(XrdXrootdMonTrace)+sizeof(XrdXrootdMonHeader);
1091  fillHeader(&monBuff->hdr, XROOTD_MON_MAPTRCE, size);
1092 
1093 // Punt on the right ending time. We are trying to keep same-sized windows
1094 // This was corrected by Matevz Tadel, as before we were using real time which
1095 // could have been far into the future due to simple inactivity. So, Place the
1096 // computed ending timing mark.
1097 //
1098  now = lastWindow + sizeWindow;
1099  setTMark(monBuff, nextEnt, now);
1100 
1101 // Send off the buffer and reinitialize it
1102 //
1103  if (this != altMon) Send(XROOTD_MON_IO, (void *)monBuff, size);
1104  else {Send(XROOTD_MON_FILE, (void *)monBuff, size);
1105  FlushTime = localWindow + autoFlush;
1106  }
1107  setTMark(monBuff, 0, localWindow);
1108  nextEnt = 1;
1109 }
1110 
1111 /******************************************************************************/
1112 
1113 void XrdXrootdMonitor::Flush(XrdXrootdMonitor::MonRdrBuff *mP)
1114 {
1115  int size;
1116 
1117 // Reset flush time but do not flush an empty buffer. We use the current time
1118 // to make sure a record atleast sits in the buffer a full flush period.
1119 //
1120  mP->flushIt = static_cast<int>(time(0)) + autoFlush;
1121  if (mP->nextEnt <= 1) return;
1122 
1123 // Set ending timing mark and force a new one on the next fill
1124 //
1125  setTMurk(mP->Buff, mP->nextEnt, rdrTOD);
1126  mP->lastTOD = 0;
1127 
1128 // Fill in the header and in the process we will have the current time
1129 //
1130  size = (mP->nextEnt+1)*sizeof(XrdXrootdMonRedir)+sizeof(XrdXrootdMonHeader)+8;
1131  fillHeader(&(mP->Buff->hdr), XROOTD_MON_MAPREDR, size);
1132 
1133 // Send off the buffer and reinitialize it
1134 //
1135  Send(XROOTD_MON_REDR, (void *)(mP->Buff), size);
1136  mP->nextEnt = 0;
1137 }
1138 
1139 /******************************************************************************/
1140 /* M a r k */
1141 /******************************************************************************/
1142 
1143 void XrdXrootdMonitor::Mark()
1144 {
1145  kXR_int32 localWindow;
1146 
1147 // Get the current window marker. Since simple memory accesses are sufficiently
1148 // synchronized, no need to lock this.
1149 //
1150  localWindow = currWindow;
1151 
1152 // Using an update provided by Matevz Tadel, UCSD, if this is an I/O buffer
1153 // mark then we will also flush the I/O buffer if all the following hold:
1154 // a) flushing enabled, b) buffer not empty, and c) covers the flush time.
1155 // We would normally do this during Tick() but that would require too much
1156 // locking in the middle of an I/O path, so we do psudo timed flushing.
1157 //
1158  if (this != altMon && autoFlash && nextEnt > 1)
1159  {kXR_int32 bufStartWindow =
1160  static_cast<kXR_int32>(ntohl(monBuff->info[0].arg2.Window));
1161  if (localWindow - bufStartWindow >= autoFlash)
1162  {Flush();
1163  lastWindow = localWindow;
1164  return;
1165  }
1166  }
1167 
1168 // Now, optimize placing the window mark in the buffer. Using another MT fix we
1169 // set the end of the previous window to be lastwindow + sizeWindow (instead of
1170 // localWindow) to prevent windows from being wrongly zero sized.
1171 //
1172  if (monBuff->info[nextEnt-1].arg0.id[0] == XROOTD_MON_WINDOW)
1173  {
1174  monBuff->info[nextEnt-1].arg2.Window =
1175  static_cast<kXR_int32>(htonl(localWindow));
1176  }
1177  else if (nextEnt+8 > lastEnt)
1178  {
1179  Flush();
1180  }
1181  else
1182  {
1183  monBuff->info[nextEnt].arg0.val = mySID;
1184  monBuff->info[nextEnt].arg0.id[0] = XROOTD_MON_WINDOW;
1185  monBuff->info[nextEnt].arg1.Window =
1186  static_cast<kXR_int32>(htonl(lastWindow + sizeWindow));
1187  monBuff->info[nextEnt].arg2.Window =
1188  static_cast<kXR_int32>(htonl(localWindow));
1189  nextEnt++;
1190  }
1191  lastWindow = localWindow;
1192 }
1193 
1194 /******************************************************************************/
1195 /* S e n d */
1196 /******************************************************************************/
1197 
1198 int XrdXrootdMonitor::Send(int monMode, void *buff, int blen, bool setseq)
1199 {
1200 #ifndef NODEBUG
1201  const char *TraceID = "Monitor";
1202 #endif
1203  static XrdSysMutex sendMutex;
1204  static int seq1=0, seq2=0;
1205  XrdXrootdMonHeader *mHdr=0;
1206  int rc1, rc2;
1207 
1208 // If we are to set sequence numbers, recast the buffer. We are assured that
1209 // the buffer always starts with the standard monitor header.
1210 //
1211  if (setseq) mHdr = static_cast<XrdXrootdMonHeader*>(buff);
1212 
1213  sendMutex.Lock();
1214  if (monMode & monMode1 && InetDest1)
1215  {if (mHdr) mHdr->pseq = (seq1++) & 0xff;
1216  rc1 = InetDest1->Send((char *)buff, blen);
1217  TRACE(DEBUG,blen <<" bytes sent to " <<Dest1 <<" rc=" <<rc1);
1218  }
1219  else rc1 = 0;
1220  if (monMode & monMode2 && InetDest2)
1221  {if (mHdr) mHdr->pseq = (seq2++) & 0xff;
1222  rc2 = InetDest2->Send((char *)buff, blen);
1223  TRACE(DEBUG,blen <<" bytes sent to " <<Dest2 <<" rc=" <<rc2);
1224  }
1225  else rc2 = 0;
1226  sendMutex.UnLock();
1227 
1228  return (rc1 ? rc1 : rc2);
1229 }
1230 
1231 /******************************************************************************/
1232 /* s t a r t C l o c k */
1233 /******************************************************************************/
1234 
1235 void XrdXrootdMonitor::startClock()
1236 {
1237  static XrdXrootdMonitor_Tick MonTick;
1238  time_t Now;
1239 
1240 // Start the clock, Caller must have windowMutex locked, if necessary.
1241 //
1242  Now = time(0);
1243  currWindow = static_cast<kXR_int32>(Now);
1244  rdrTOD = htonl(currWindow);
1245  MonTick.Set(Sched, sizeWindow);
1246  FlushTime = autoFlush + currWindow;
1247  if (Sched) Sched->Schedule((XrdJob *)&MonTick, Now+sizeWindow);
1248 }
int kXR_int32
Definition: XPtypes.hh:89
unsigned int kXR_unt32
Definition: XPtypes.hh:90
unsigned char kXR_char
Definition: XPtypes.hh:65
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
static XrdSysError eDest(0,"crypto_")
#define XROOTD_MON_INFO
XrdOucString Path
size_t strlcpy(char *dst, const char *src, size_t sz)
#define TRACE(act, x)
Definition: XrdTrace.hh:63
union XrdXrootdMonRedir::@173 arg1
const kXR_char XROOTD_MON_DISC
const kXR_char XROOTD_MON_MAPUEAC
const kXR_char XROOTD_MON_WINDOW
union XrdXrootdMonTrace::@170 arg1
XrdXrootdMonTrace info[sizeof(XrdXrootdMonTrace)]
const kXR_char XROOTD_MON_MAPUSER
const kXR_char XROOTD_MON_APPID
union XrdXrootdMonTrace::@169 arg0
const kXR_char XROOTD_MON_REDSID
const kXR_char XROOTD_MON_MAPIDNT
const kXR_char XROOTD_MON_MAPTRCE
char info[1024+256]
const kXR_char XROOTD_MON_CLOSE
union XrdXrootdMonTrace::@171 arg2
const kXR_char XROOTD_MON_MAPPATH
XrdXrootdMonHeader hdr
const kXR_char XROOTD_MON_OPEN
XrdXrootdMonHeader hdr
const kXR_char XROOTD_MON_REDIRECT
const kXR_char XROOTD_MON_MAPTOKN
union XrdXrootdMonRedir::@172 arg0
const kXR_char XROOTD_MON_MAPREDR
XrdSysTrace XrdXrootdTrace
#define setTMurk(TM_mb, TM_en, TM_tm)
#define setTMark(TM_mb, TM_en, TM_tm)
#define XROOTD_MON_IOV
#define XROOTD_MON_ALL
#define XROOTD_MON_AUTH
#define XROOTD_MON_IO
#define XROOTD_MON_USER
#define XROOTD_MON_FSTA
#define XROOTD_MON_PATH
#define XROOTD_MON_FILE
#define XROOTD_MON_REDR
Definition: XrdJob.hh:43
int Send(const char *buff, int blen=0, const char *dest=0, int tmo=-1)
Definition: XrdNetMsg.cc:70
static int Export(const char *Var, const char *Val)
Definition: XrdOucEnv.cc:188
static char * Ident(long long &mySID, char *iBuff, int iBlen, const char *iHost, const char *iProg, const char *iName, int Port)
Definition: XrdOucUtils.cc:702
void Schedule(XrdJob *jp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static void Defaults(int intv, int opts, int iocnt, int fbsz)
static bool Init()
XrdXrootdMonitorLock(XrdXrootdMonitor *theMonitor)
Hello(const char *dest, char mode)
void Register(const char *Uname, const char *Hname, const char *Pname, unsigned int xSID=0)
void Report(const char *Info)
XrdXrootdMonitor_Ident(int idt, bool ison)
void Set(XrdScheduler *sp, int intvl)
static const int rdrMax
static XrdXrootdMonitor * altMon
static void Ident()
static void Defaults(char *dest1, int m1, char *dest2, int m2)
void appID(char *id)
static time_t Tick()
void Disc(kXR_unt32 dictid, int csec, char Flags=0)
void Close(kXR_unt32 dictid, long long rTot, long long wTot)
static int Send(int mmode, void *buff, int size, bool setseq=true)
static int Redirect()
void Open(kXR_unt32 dictid, off_t fsize)
static kXR_unt32 GetDictID(bool hbo=false)
XrdScheduler Sched
Definition: XrdLinkCtl.cc:54
XrdScheduler * Sched
XrdSysError * eDest
static int32_t InitStartTime()