36 #include <sys/types.h>
51 {
bool operator()(
const char *a,
const char *b)
52 const {
return strcmp(a,b) < 0;}
55 std::map<const char *, const char *, vCmp> vnMap {
57 {
"src",
"Server location:"},
58 {
"tod",
"~Statistics:"},
59 {
"tos",
"~Server started: "},
60 {
"pgm",
"Server program: "},
61 {
"ins",
"Server instance:"},
62 {
"pid",
"Server process: "},
63 {
"site",
"Server sitename: "},
64 {
"ver",
"Server version: "},
65 {
"info.host",
"Host name:"},
66 {
"info.port",
"Port:"},
67 {
"info.name",
"Instance name:"},
68 {
"buff.reqs",
"Buffer requests:"},
69 {
"buff.mem",
"Buffer bytes:"},
70 {
"buff.buffs",
"Buffer count:"},
71 {
"buff.adj",
"Buffer adjustments:"},
72 {
"buff.xlreqs",
"Buffer XL requests:"},
73 {
"buff.xlmem",
"Buffer XL bytes:"},
74 {
"buff.xlbuffs",
"Buffer XL count:"},
75 {
"link.num",
"Current connections:"},
76 {
"link.maxn",
"Maximum connections:"},
77 {
"link.tot",
"Overall connections:"},
78 {
"link.in",
"Bytes received:"},
79 {
"link.out",
"Bytes sent:"},
80 {
"link.ctime",
"Total connect seconds:"},
81 {
"link.tmo",
"Read request timeouts:"},
82 {
"link.stall",
"Number of partial reads:"},
83 {
"link.sfps",
"Number of partial sends:"},
84 {
"poll.att",
"Poll sockets:"},
85 {
"poll.en",
"Poll enables:"},
86 {
"poll.ev",
"Poll events: "},
87 {
"poll.int",
"Poll events unsolicited:"},
88 {
"proc.usr.s",
"Seconds user time:"},
89 {
"proc.usr.u",
"Micros user time:"},
90 {
"proc.sys.s",
"Seconds sys time:"},
91 {
"proc.sys.u",
"Micros sys time:"},
92 {
"xrootd.num",
"XRootD protocol loads:"},
93 {
"xrootd.ops.open",
"XRootD opens:"},
94 {
"xrootd.ops.rf",
"XRootD cache refreshes:"},
95 {
"xrootd.ops.rd",
"XRootD reads:"},
96 {
"xrootd.ops.pr",
"XRootD preads:"},
97 {
"xrootd.ops.rv",
"XRootD readv's:"},
98 {
"xrootd.ops.rs",
"XRootD readv segments:"},
99 {
"xrootd.ops.wr",
"XRootD writes:"},
100 {
"xrootd.ops.sync",
"XRootD syncs:"},
101 {
"xrootd.ops.getf",
"XRootD getfiles:"},
102 {
"xrootd.ops.putf",
"XRootD putfiles:"},
103 {
"xrootd.ops.misc",
"XRootD misc requests:"},
104 {
"xrootd.sig.ok",
"XRootD ok signatures:"},
105 {
"xrootd.sig.bad",
"XRootD bad signatures:"},
106 {
"xrootd.sig.ign",
"XRootD ign signatures:"},
107 {
"xrootd.aio.num",
"XRootD aio requests:"},
108 {
"xrootd.aio.max",
"XRootD aio max requests:"},
109 {
"xrootd.aio.rej",
"XRootD aio rejections:"},
110 {
"xrootd.err",
"XRootD request failures:"},
111 {
"xrootd.rdr",
"XRootD request redirects:"},
112 {
"xrootd.dly",
"XRootD request delays:"},
113 {
"xrootd.lgn.num",
"XRootD login total count:"},
114 {
"xrootd.lgn.af",
"XRootD login auths bad: "},
115 {
"xrootd.lgn.au",
"XRootD login auths good: "},
116 {
"xrootd.lgn.ua",
"XRootD login auths none: "},
117 {
"ofs.role",
"Server role:"},
118 {
"ofs.opr",
"Ofs reads:"},
119 {
"ofs.opw",
"Ofs writes:"},
120 {
"ofs.opp",
"POSC files now open:"},
121 {
"ofs.ups",
"POSC files deleted:"},
122 {
"ofs.han",
"Ofs handles:"},
123 {
"ofs.rdr",
"Ofs redirects:"},
124 {
"ofs.bxq",
"Ofs background tasks:"},
125 {
"ofs.rep",
"Ofs callbacks:"},
126 {
"ofs.err",
"Ofs errors:"},
127 {
"ofs.dly",
"Ofs delays:"},
128 {
"ofs.sok",
"Ofs ok events:"},
129 {
"ofs.ser",
"Ofs bad events:"},
130 {
"ofs.tpc.grnt",
"TPC grants:"},
131 {
"ofs.tpc.deny",
"TPC denials:"},
132 {
"ofs.tpc.err",
"TPC errors:"},
133 {
"ofs.tpc.exp",
"TPC expires:"},
134 {
"oss.paths",
"Oss exports:"},
135 {
"oss.space",
"Oss space:"},
136 {
"sched.jobs",
"Tasks scheduled: "},
137 {
"sched.inq",
"Tasks now queued:"},
138 {
"sched.maxinq",
"Max tasks queued:"},
139 {
"sched.threads",
"Threads in pool:"},
140 {
"sched.idle",
"Threads idling: "},
141 {
"sched.tcr",
"Threads created:"},
142 {
"sched.tde",
"Threads deleted:"},
143 {
"sched.tlimr",
"Threads unavail:"},
144 {
"sgen.as",
"Unsynchronized stats:"},
145 {
"sgen.et",
"Mills to collect stats:"},
146 {
"sgen.toe",
"~Time when stats collected:"},
147 {
"ssi.err",
"SSI errors:"},
148 {
"ssi.req.bytes",
"Request total bytes:"},
149 {
"ssi.req.maxsz",
"Request largest size:"},
150 {
"ssi.req.ab",
"Request aborts:"},
151 {
"ssi.req.al",
"Request alerts:"},
152 {
"ssi.req.bnd",
"Requests now bound:"},
153 {
"ssi.req.can",
"Requests cancelled:"},
154 {
"ssi.req.cnt",
"Request total count:"},
155 {
"ssi.req.fin",
"Requests finished:"},
156 {
"ssi.req.finf",
"Requests forced off:"},
157 {
"ssi.req.gets",
"Request retrieved:"},
158 {
"ssi.req.perr",
"Request prep errors:"},
159 {
"ssi.req.proc",
"Requests started:"},
160 {
"ssi.req.rdr",
"Requests redirected:"},
161 {
"ssi.req.relb",
"Request buff releases:"},
162 {
"ssi.req.dly",
"Requests delayed:"},
163 {
"ssi.rsp.bad",
"Response violations:"},
164 {
"ssi.rsp.cbk",
"Response callbacks:"},
165 {
"ssi.rsp.data",
"Responses as data:"},
166 {
"ssi.rsp.errs",
"Responses as errors:"},
167 {
"ssi.rsp.file",
"Responses as files:"},
168 {
"ssi.rsp.rdy",
"Responses without delay:"},
169 {
"ssi.rsp.str",
"Responses as streams:"},
170 {
"ssi.rsp.unr",
"Responses with delay:"},
171 {
"ssi.rsp.mdb",
"Response metadata bytes:"},
172 {
"ssi.res.add",
"Resources added:"},
173 {
"ssi.res.rem",
"Resources removed:"}
188 int Pop(
const char *vName);
190 int Push(
const char *vName);
192 void Reset() {vEnd = vBuff; vNum = -1; *vBuff = 0;}
194 const char *
Var() {
return vBuff;}
197 : vFence(vBuff + sizeof(vBuff) - 1), Debug(dbg) {
Reset();}
201 static const int vMax = 15;
202 char *vEnd, *vFence, *vStack[vMax+1], vBuff[1024];
213 if (Debug) std::cerr <<
"Pop: " <<(vName ? vName :
"") <<
"; var=" <<vBuff <<std::endl;
214 if (vNum < 0 || (vName && strcmp(vStack[vNum], vName)))
return 0;
215 vEnd = vStack[vNum]-1; *vEnd =
'\0'; vNum--;
225 int n = strlen(vName);
227 if (Debug) std::cerr <<
"Push: " <<vName <<
"; var=" <<vBuff <<std::endl;
228 if (vNum >= vMax)
return 0;
229 if (vNum >= 0) *vEnd++ =
'.';
231 if (vEnd+n+1 >= vFence)
return 0;
233 vStack[++vNum] = vEnd;
244 static const char *Hdr0 =
"<statistics ";
245 static const int H0Len = strlen(Hdr0);
249 VarInfo vHead[] = {{
"tod", 0}, {
"ver", 0}, {
"src", 0}, {
"tos", 0},
250 {
"pgm", 0}, {
"ins", 0}, {
"pid", 0}, {0, 0}};
251 VarInfo vStat[] = {{
"id", 0}, {0, 0}};
252 VarInfo vTail[] = {{
"toe", 0}, {0, 0}};
253 char *lP = ibuff, *oP = obuff, *tP, *vP;
258 if (!(lP = (
char *)index(lP,
'>')))
259 return xmlErr(
"Invalid xml stream: ", ibuff);
265 {
if (*lP ==
'>' || (*lP ==
'<' && *(lP+1) ==
'/')) *lP =
' ';
271 if (!(lP = Data.
GetLine()) || strncmp(Hdr0, lP, H0Len))
272 return xmlErr(
"Stream does not start with '<statistics'.");
273 Data.
GetToken(); getVars(Data, vHead);
277 for (i = 0; vHead[i].Name; i++)
278 {
if (vHead[i].Data) oP = Add(oP, vHead[i].Name, vHead[i].Data);}
282 if (Host) oP = Add(oP,
"host", Host);
286 if (!Data.
GetLine())
return xmlErr(
"Null xml stream after header.");
290 while((tP = Data.
GetToken()) && strcmp(tP,
"/statistics"))
292 {
if (!xVar.
Pop(strcmp(
"/stats", tP) ? tP+1 : 0))
293 return xmlErr(tP,
"invalid end for ", xVar.
Var());
296 {
if (strcmp(
"<stats", tP)) rc = xVar.
Push(tP+1);
297 else {getVars(Data, vStat);
298 rc = (vStat[0].Data ? xVar.
Push(vStat[0].Data)
301 if (!rc)
return xmlErr(
"Nesting too deep for ", xVar.
Var());
303 else {
if ((vP = index(tP,
'<'))) *vP =
'\0';
306 if (*(tP+i) ==
'"') {*(tP+i) =
'\0'; i = 1;}
308 oP = Add(oP, xVar.
Var(), tP+i);
310 if (vP != tP) memset(tP,
' ', vP - tP);
315 if (!tP)
return xmlErr(
"Missing '</statistics>' in xml stream.");
316 getVars(Data, vTail);
317 if (vTail[0].Data) oP = Add(oP, vTail[0].Name, vTail[0].Data);
318 if (*(oP-1) ==
'&') oP--;
327 char *XrdMpxXml::Add(
char *Buff,
const char *Var,
const char *Val)
331 if (noZed && !strcmp(
"0", Val))
return Buff;
334 {std::map<const char *, const char *, vCmp>::iterator it;
335 it = vnMap.find(Var);
336 if (it != vnMap.end())
339 {time_t tod = atoi(Val);
342 {
struct tm *tInfo = localtime(&tod);
343 strftime(tmBuff,
sizeof(tmBuff),
"%a %F %T", tInfo);
350 strcpy(Buff, Var); Buff += strlen(Var);
352 strcpy(Buff, Val); Buff += strlen(Val);
371 while(Var[i].Name) Var[i++].Data = 0;
375 while((tVar = Data.
GetToken()) && *tVar !=
'<' && *tVar !=
'/')
376 {
if (!(tVal = (
char *)index(tVar,
'=')))
continue;
379 {tVal++, i = strlen(tVal);
380 if (*(tVal+i-1) ==
'"') *(tVal+i-1) =
'\0';
384 {
if (!strcmp(Var[i].Name, tVar)) {Var[i].Data = tVal;
break;}
388 if (tVar && (*tVar ==
'<' || *tVar ==
'/')) Data.
RetToken();
395 int XrdMpxXml::xmlErr(
const char *t1,
const char *t2,
const char *t3)
397 std::cerr <<
"XrdMpxXml: " <<t1 <<
' ' <<t2 <<
' ' <<t3 <<std::endl;
int Push(const char *vName)
XrdMpxVar(bool dbg=false)
int Pop(const char *vName)
int Format(const char *Host, char *ibuff, char *obuff)
char * GetToken(char **rest=0, int lowcase=0)