40#include "XrdVersion.hh"
57char *XrdXrootdMonitor::idRec = 0;
58int XrdXrootdMonitor::idLen = 0;
59char *XrdXrootdMonitor::Dest1 = 0;
60int XrdXrootdMonitor::monMode1 = 0;
61XrdNetMsg *XrdXrootdMonitor::InetDest1 = 0;
62char *XrdXrootdMonitor::Dest2 = 0;
63int XrdXrootdMonitor::monMode2 = 0;
64XrdNetMsg *XrdXrootdMonitor::InetDest2 = 0;
67int XrdXrootdMonitor::monRlen = 0;
68XrdXrootdMonitor::MonRdrBuff
70XrdXrootdMonitor::MonRdrBuff
71 *XrdXrootdMonitor::rdrMP = 0;
73int XrdXrootdMonitor::monBlen = 0;
74int XrdXrootdMonitor::lastEnt = 0;
75int XrdXrootdMonitor::lastRnt = 0;
76int XrdXrootdMonitor::isEnabled = 0;
77int XrdXrootdMonitor::numMonitor = 0;
78int XrdXrootdMonitor::autoFlash = 0;
79int XrdXrootdMonitor::autoFlush = 600;
80int XrdXrootdMonitor::FlushTime = 0;
81int XrdXrootdMonitor::monIdent = 3600;
82kXR_int32 XrdXrootdMonitor::currWindow = 0;
83int XrdXrootdMonitor::rdrTOD = 0;
84int XrdXrootdMonitor::rdrWin = 0;
85int XrdXrootdMonitor::rdrNum = 3;
86kXR_int32 XrdXrootdMonitor::sizeWindow = 60;
87char XrdXrootdMonitor::monINFO = 0;
88char XrdXrootdMonitor::monIO = 0;
89char XrdXrootdMonitor::monFILE = 0;
90char XrdXrootdMonitor::monREDR = 0;
91char XrdXrootdMonitor::monUSER = 0;
92char XrdXrootdMonitor::monAUTH = 0;
93char XrdXrootdMonitor::monACTIVE = 0;
94char XrdXrootdMonitor::monFSTAT = 0;
95char XrdXrootdMonitor::monCLOCK = 0;
108 return htonl( time( 0 ) );
132#define setTMark(TM_mb, TM_en, TM_tm) \
133 TM_mb->info[TM_en].arg0.val = mySID; \
134 TM_mb->info[TM_en].arg0.id[0] = XROOTD_MON_WINDOW; \
135 TM_mb->info[TM_en].arg1.Window = \
136 TM_mb->info[TM_en].arg2.Window = static_cast<kXR_int32>(ntohl(TM_tm));
138#define setTMurk(TM_mb, TM_en, TM_tm) \
139 TM_mb->info[TM_en].arg0.Window = rdrWin; \
140 TM_mb->info[TM_en].arg1.Window = static_cast<kXR_int32>(TM_tm);
158 if ((doIdnt || doHail) && idInt > 0)
163 idInt(idt), doIdnt(ison), doHail(true) {}
182 const char *TraceID =
"MonTick";
186 Sched->Schedule((
XrdJob *)
this, Now+Window);
187 else {
TRACE(
DEBUG,
"Monitor clock stopping.");}
193 Sched(0), Window(0) {}
209static void Lock() {monLock.Lock();}
215 else {unLock = 1; monLock.Lock();}
232 : Next(0), theDest(0), theMode(0)
236 while(nP) {
if (!strcmp(dest, nP->theDest) && mode == theMode)
return;
241 theDest = strdup(dest);
258 while(nP) {nP->
Ident(); nP = nP->Next;}
272 {XrdXrootdMonitor::unAlloc(
Agent);
Agent = 0;}
282 if (
Agent || (
Agent = XrdXrootdMonitor::Alloc(1)))
283 {
Iops = XrdXrootdMonitor::monIO;
284 Fops = XrdXrootdMonitor::monFILE;
294 const char *Pname,
unsigned int xSID)
297 const char *TraceID =
"Monitor";
299 char *dotP, *colonP, *atP;
300 char uBuff[1024], tBuff[1024], sBuff[64];
305 snprintf(tBuff,
sizeof(tBuff),
"%s", Uname);
306 if ((dotP = index(tBuff,
'.')) && (colonP = index(dotP+1,
':')) &&
307 (atP = index(colonP+1,
'@')))
308 {*dotP = 0; *colonP = 0; *atP = 0;
310 {snprintf(sBuff,
sizeof(sBuff),
" %u", xSID);
314 int n = snprintf(uBuff,
sizeof(uBuff),
"%s/%s.%s:%s@%s", Pname, tBuff,
315 dotP+1,
kySID, atP+1);
317 if (n < 0 || n >= (
int)
sizeof(uBuff))
318 TRACE(LOGIN,
"Login ID was truncated: " << uBuff);
320 if (xSID) {
TRACE(LOGIN,
"Register remap "<<Uname<<
" -> "<<uBuff);}
321 }
else snprintf(uBuff,
sizeof(uBuff),
"%s/%s", Pname, Uname);
326 Agent = XrdXrootdMonitor::Alloc();
329 Name = strdup(uBuff);
330 Iops = XrdXrootdMonitor::monIO;
331 Fops = XrdXrootdMonitor::monFILE;
342 snprintf(buff,
sizeof(buff),
"&Uc=%u&Ec=%d&Ac=%d", ntohl(
Did), eCode, aCode);
357 snprintf(buff,
sizeof(buff),
"&Uc=%u%s%s", ntohl(
Did),
358 (*info ==
'&' ?
"" :
"&"), info);
375 localWindow = currWindow;
379 if (posix_memalign((
void **)&monBuff, getpagesize(), monBlen))
380 eDest->
Emsg(
"Monitor",
"Unable to allocate monitor buffer.");
390XrdXrootdMonitor::~XrdXrootdMonitor()
393 if (monBuff) {Flush(); free(monBuff);}
406 if (
this ==
altMon || !*
id)
return;
410 if (lastWindow != currWindow) Mark();
411 else if (nextEnt == lastEnt) Flush();
413 strncpy((
char *)(&(monBuff->info[nextEnt])+4),
id, apInfoSize);
429 if (!isEnabled) mp = 0;
430 else if (!monIO) mp =
altMon;
432 if (!(mp->monBuff)) {
delete mp; mp = 0;}
436 if (mp && isEnabled < 0)
438 lastVal = numMonitor; numMonitor++;
439 if (!lastVal && !monREDR) startClock();
440 windowMutex.UnLock();
455 unsigned int rVal, wVal;
459 if (lastWindow != currWindow) Mark();
460 else if (nextEnt == lastEnt) Flush();
462 monBuff->info[nextEnt].arg0.id[1] = do_Shift(rTot, rVal);
463 monBuff->info[nextEnt].arg0.rTot[1] = htonl(rVal);
464 monBuff->info[nextEnt].arg0.id[2] = do_Shift(wTot, wVal);
465 monBuff->info[nextEnt].arg0.id[3] = 0;
466 monBuff->info[nextEnt].arg1.wTot = htonl(wVal);
467 monBuff->info[nextEnt++].arg2.dictid = dictid;
485 if (room <= 0)
return 0;
486 if (tLen > room - 1) tLen = room - 1;
487 memcpy(buff, text, tLen);
488 memset(buff + tLen, 0, room - tLen);
505 if (!dest1 && !dest2) {isEnabled = 0;
return;}
506 if (!dest1) {dest1 = dest2; dest2 = 0; mode1 |= mode2; mode2 = 0;}
510 if (Dest1) free(Dest1);
511 Dest1 = dest1; monMode1 = mode1;
512 if (Dest2) free(Dest2);
513 Dest2 = dest2; monMode2 = mode2;
517 mmode = mode1 | mode2;
518 monACTIVE = (mmode ? 1 : 0);
531 if (monREDR || (isEnabled > 0 && (monIO || monFILE))) monCLOCK = 1;
551 int flush,
int flash,
int idt,
int rnm,
552 int fbsz,
int fsint,
int fsopt,
int fsion)
557 sizeWindow = (wsz <= 0 ? 60 : wsz);
558 autoFlush = (flush <= 0 ? 600 : flush);
559 autoFlash = (flash <= 0 ? 0 : flash);
561 rdrNum = (rnm <= 0 || rnm >
rdrMax ? 3 : rnm);
562 rdrWin = (sizeWindow > 16777215 ? 16777215 : sizeWindow);
563 rdrWin = htonl(rdrWin);
568 monFSTAT = fsint != 0;
573 if (msz <= 0) msz = 16384;
574 else if (msz < 1024) msz = 1024;
584 if (rsz <= 0) rsz = 32768;
585 else if (rsz < 2048) rsz = 2048;
606 if (lastWindow != currWindow) Mark();
607 else if (nextEnt == lastEnt) Flush();
608 monBuff->info[nextEnt].arg0.rTot[0] = 0;
610 monBuff->info[nextEnt].arg0.id[1] = Flags;
611 monBuff->info[nextEnt].arg1.wTot = htonl(csec);
612 monBuff->info[nextEnt++].arg2.dictid = dictid;
617 altMon->Dup(&monBuff->info[nextEnt-1]);
630 if (lastWindow != currWindow) Mark();
631 else if (nextEnt == lastEnt) Flush();
640XrdXrootdMonitor::MonRdrBuff *XrdXrootdMonitor::Fetch()
647 if ((bP = rdrMP)) rdrMP = rdrMP->Next;
657 const char *iHost,
const char *iProg,
658 const char *iName,
int Port)
660 const char *cgID0 =
"&site=%s";
661 const char *cgID1 =
"&host=%s";
662 const char *cgID2 =
"&port=%d&inst=%s";
663 const char *cgID3 =
"&pgm=%s&ver=%s";
665 const char *jsID0 =
"\"src\":{\"site\":\"%s\"}";
666 const char *jsID1 =
"%s\"host\":\"%s\"}";
667 const char *jsID2 =
"%s\"port\":%d,\"inst\":\"%s\"}";
668 const char *jsID3 =
"%s\"pgm\":\"%s\",\"ver\":\"%s\"}";
671 char iBuff[1024], iMuff[2048], iPuff[1024];
683 iHost, iProg, iName, Port);
685 snprintf(iBuff+n,
sizeof(iBuff)-n,
"&ver=%s", XrdVERSION);
692#if defined(__GNUC__) && __GNUC__ >= 12
693#pragma GCC diagnostic push
694#pragma GCC diagnostic ignored "-Warray-bounds"
699 idRec = (
char *)malloc(idLen+1);
704 strcpy(mP->
info, iBuff);
705#if defined(__GNUC__) && __GNUC__ >= 12
706#pragma GCC diagnostic pop
711 const char *Site (getenv(
"XRDSITE") ? getenv(
"XRDSITE") :
"");
712 i = snprintf(iPuff,
sizeof(iPuff), cgID0, Site);
713 SidCGI[0] = strdup(iPuff);
714 LidCGI[0] = strlen(iPuff);
716 n =
sizeof(iPuff)-i; j = i;
717 i = snprintf(iPuff+j, n, cgID1, iHost);
718 SidCGI[1] = strdup(iPuff);
719 LidCGI[1] = strlen(iPuff);
722 i = snprintf(iPuff+j, n, cgID2, Port, iName);
723 SidCGI[2] = strdup(iPuff);
724 LidCGI[2] = strlen(iPuff);
727 snprintf(iPuff+j, n, cgID3, iProg, XrdVERSION);
728 SidCGI[3] = strdup(iPuff);
729 LidCGI[3] = strlen(iPuff);
733 n = snprintf(iPuff,
sizeof(iPuff), jsID0, Site);
737 strcpy(iPuff+n-1,
",");
738 n = snprintf(iMuff,
sizeof(iMuff), jsID1, iPuff, iHost);
742 strcpy(iMuff+n-1,
",");
743 n = snprintf(iPuff,
sizeof(iPuff), jsID2, iMuff, Port, iName);
747 strcpy(iPuff+n-1,
",");
748 snprintf(iMuff,
sizeof(iMuff), jsID3, iPuff, iProg, XrdVERSION);
758 int i, Now = time(0);
766 {
eDest->
Emsg(
"Monitor",
"Unable to setup primary monitor collector.");
776 {
eDest->
Emsg(
"Monitor",
"Unable to setup secondary monitor collector.");
787 if (!isEnabled)
return 1;
796 eDest->
Emsg(
"Monitor",
"allocate monitor; insufficient storage.");
802 if (monCLOCK) startClock();
806 if (!
Sched || !monFSTAT) monFSTAT = 0;
811 if (!monREDR)
return 1;
815 for (i = 0; i < rdrNum; i++)
816 {
if (posix_memalign((
void **)&rdrMon[i].Buff, getpagesize(),monRlen))
817 {
eDest->
Emsg(
"Monitor",
"Unable to allocate monitor rdr buffer.");
820 rdrMon[i].Buff->sID =
mySID;
822 rdrMon[i].Next = (i ? &rdrMon[i-1] : &rdrMon[0]);
823 rdrMon[i].nextEnt = 0;
824 rdrMon[i].flushIt = Now + autoFlush;
825 rdrMon[i].lastTOD = 0;
827 rdrMon[0].Next = &rdrMon[i-1];
842 static unsigned int monSeqID = 1;
843 unsigned int mySeqID;
848 mySeqID = monSeqID++;
853 if (hbo)
return mySeqID;
854 return htonl(mySeqID);
865 const int room =
sizeof(map.
info);
876 if (path && size < room - 2)
877 {
int pLen = strlen(path);
878 map.
info[size++] =
'\n';
879 size +=
CopyText(map.
info + size, std::min(pLen + 1, room - size),
885 size =
sizeof(XrdXrootdMonHeader)+
sizeof(
kXR_int32)+size;
886 fillHeader(&map.
hdr, code, size);
895 Send(montype, (
void *)&map, size);
910 if (lastWindow != currWindow) Mark();
911 else if (nextEnt == lastEnt) Flush();
912 h2nll(fsize, monBuff->info[nextEnt].arg0.val);
914 monBuff->info[nextEnt].arg1.buflen = 0;
915 monBuff->info[nextEnt++].arg2.dictid = dictid;
927 char opC,
const char *
Path)
930 MonRdrBuff *mP = Fetch();
931 int n, slots, hLen, pLen, room;
936 if (*hName ==
'/') {
Path = hName; hName =
""; hLen = 0;}
937 else {
const char *quest = index(hName,
'?');
938 hLen = (quest ? quest - hName : strlen(hName));
939 if (hLen > 256) hLen = 256;
947 if (pLen > 1024) pLen = 1024;
951 n = (hLen + 1 + pLen + 1);
964 if (mP->nextEnt + slots + 2 >= lastRnt) Flush(mP);
968 if (mP->lastTOD != rdrTOD)
969 {mP->lastTOD = rdrTOD;
970 setTMurk(mP->Buff, mP->nextEnt, mP->lastTOD);
976 mtP = &(mP->Buff->
info[mP->nextEnt]);
978 mtP->
arg0.rdr.Dent =
static_cast<char>(slots);
979 mtP->
arg0.rdr.Port = htons(
static_cast<short>(Port));
980 mtP->
arg1.dictid = mID;
981 dest = (
char *)(mtP+1);
982 strncpy(dest, hName,hLen); dest += hLen; *dest++ =
':';
987 mP->nextEnt = mP->nextEnt + (slots+1);
999 time_t Now = time(0);
1005 currWindow =
static_cast<kXR_int32>(Now);
1006 rdrTOD = htonl(currWindow);
1007 nextFlush = currWindow + autoFlush;
1011 if (
altMon && currWindow >= FlushTime)
1013 if (currWindow >= FlushTime)
1015 else FlushTime = nextFlush;
1025 {rdrMon[n].Mutex.Lock();
1026 if (rdrMon[n].nextEnt == 0) rdrMon[n].flushIt = nextFlush;
1027 else if (rdrMon[n].flushIt <= currWindow) Flush(&rdrMon[n]);
1028 rdrMon[n].Mutex.UnLock();
1036 if (!monREDR && isEnabled < 0)
1037 {windowMutex.Lock();
1038 if (!numMonitor) Now = 0;
1039 windowMutex.UnLock();
1053 if (monp !=
altMon)
delete monp;
1058 {windowMutex.
Lock();
1071unsigned char XrdXrootdMonitor::do_Shift(
long long xTot,
unsigned int &xVal)
1073 const long long smask = 0x7fffffff00000000LL;
1074 const long long xmask = 0x7fffffffffffffffLL;
1075 unsigned char xshift = 0;
1078 while(xTot & smask) {xTot = xTot >> 1LL; xshift++;}
1079 xVal =
static_cast<unsigned int>(xTot);
1088void XrdXrootdMonitor::fillHeader(XrdXrootdMonHeader *hdr,
1089 const char id,
int size)
1096 hdr->
plen = htons(
static_cast<uint16_t
>(size));
1104void XrdXrootdMonitor::Flush()
1111 if (nextEnt <= 1)
return;
1116 localWindow = currWindow;
1120 size = (nextEnt+1)*
sizeof(XrdXrootdMonTrace)+
sizeof(XrdXrootdMonHeader);
1128 now = lastWindow + sizeWindow;
1135 FlushTime = localWindow + autoFlush;
1143void XrdXrootdMonitor::Flush(XrdXrootdMonitor::MonRdrBuff *mP)
1150 mP->flushIt =
static_cast<int>(time(0)) + autoFlush;
1151 if (mP->nextEnt <= 1)
return;
1155 setTMurk(mP->Buff, mP->nextEnt, rdrTOD);
1160 size = (mP->nextEnt+1)*
sizeof(XrdXrootdMonRedir)+
sizeof(XrdXrootdMonHeader)+8;
1173void XrdXrootdMonitor::Mark()
1180 localWindow = currWindow;
1188 if (
this !=
altMon && autoFlash && nextEnt > 1)
1190 static_cast<kXR_int32>(ntohl(monBuff->info[0].arg2.Window));
1191 if (localWindow - bufStartWindow >= autoFlash)
1193 lastWindow = localWindow;
1204 monBuff->info[nextEnt-1].arg2.Window =
1205 static_cast<kXR_int32>(htonl(localWindow));
1207 else if (nextEnt+8 > lastEnt)
1213 monBuff->info[nextEnt].arg0.val =
mySID;
1215 monBuff->info[nextEnt].arg1.Window =
1216 static_cast<kXR_int32>(htonl(lastWindow + sizeWindow));
1217 monBuff->info[nextEnt].arg2.Window =
1218 static_cast<kXR_int32>(htonl(localWindow));
1221 lastWindow = localWindow;
1231 const char *TraceID =
"Monitor";
1234 static int seq1=0, seq2=0;
1244 if (monMode & monMode1 && InetDest1)
1245 {
if (mHdr) mHdr->
pseq = (seq1++) & 0xff;
1246 rc1 = InetDest1->Send((
char *)buff, blen);
1247 TRACE(
DEBUG,blen <<
" bytes sent to " <<Dest1 <<
" rc=" <<rc1);
1250 if (monMode & monMode2 && InetDest2)
1251 {
if (mHdr) mHdr->
pseq = (seq2++) & 0xff;
1252 rc2 = InetDest2->Send((
char *)buff, blen);
1253 TRACE(
DEBUG,blen <<
" bytes sent to " <<Dest2 <<
" rc=" <<rc2);
1258 return (rc1 ? rc1 : rc2);
1265void XrdXrootdMonitor::startClock()
1273 currWindow =
static_cast<kXR_int32>(Now);
1274 rdrTOD = htonl(currWindow);
1276 FlushTime = autoFlush + currWindow;
XrdSysError eDest(0, "HttpMon")
XrdSysTrace XrdXrootdTrace
const kXR_char XROOTD_MON_DISC
const kXR_char XROOTD_MON_MAPUEAC
const kXR_char XROOTD_MON_WINDOW
XrdXrootdMonTrace info[sizeof(XrdXrootdMonTrace)]
const kXR_char XROOTD_MON_MAPUSER
const kXR_char XROOTD_MON_APPID
const kXR_char XROOTD_MON_REDSID
const kXR_char XROOTD_MON_MAPIDNT
const kXR_char XROOTD_MON_MAPTRCE
union XrdXrootdMonRedir::@017044370107177241030156067342362323316131075335 arg0
const kXR_char XROOTD_MON_CLOSE
const kXR_char XROOTD_MON_MAPPATH
union XrdXrootdMonRedir::@124330332126055120131203275034312305071227313005 arg1
const kXR_char XROOTD_MON_OPEN
const kXR_char XROOTD_MON_REDIRECT
const kXR_char XROOTD_MON_MAPTOKN
const kXR_char XROOTD_MON_MAPREDR
#define setTMurk(TM_mb, TM_en, TM_tm)
#define setTMark(TM_mb, TM_en, TM_tm)
friend class XrdScheduler
XrdJob(const char *desc="")
XrdNetMsg(XrdSysError *erp, const char *dest=0, bool *aOK=0, bool refr=false)
static int Export(const char *Var, const char *Val)
static char * Ident(long long &mySID, char *iBuff, int iBlen, const char *iHost, const char *iProg, const char *iName, int Port)
void Schedule(XrdJob *jp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
static void Defaults(int intv, int opts, int iocnt, int fbsz)
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)
~XrdXrootdMonitor_Ident()
void Set(XrdScheduler *sp, int intvl)
static int CopyText(char *buff, int room, const char *text, int tLen)
static XrdXrootdMonitor * altMon
static void Defaults(char *dest1, int m1, char *dest2, int m2)
static constexpr int maxDgram
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)
void Open(kXR_unt32 dictid, off_t fsize)
static kXR_unt32 GetDictID(bool hbo=false)
static int32_t InitStartTime()
XrdXrootdMonRedir info[sizeof(XrdXrootdMonRedir)]