XRootD
Loading...
Searching...
No Matches
XrdMpxXml.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d M p x X m l . c c */
4/* */
5/* (c) 2018 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 <iostream>
32#include <map>
33#include <cstdio>
34#include <cstring>
35#include <unistd.h>
36#include <sys/types.h>
37#include <sys/uio.h>
38#include <ctime>
39
40#include "XrdApps/XrdMpxXml.hh"
42
43
44/******************************************************************************/
45/* v n M a p D e f i n i t i o n */
46/******************************************************************************/
47
48namespace
49{
50struct vCmp
51 {bool operator()(const char *a, const char *b)
52 const {return strcmp(a,b) < 0;}
53 };
54
55std::map<const char *, const char *, vCmp> vnMap {
56
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:"}
174};
175}
176
177/******************************************************************************/
178/* L o c a l C l a s s e s */
179/******************************************************************************/
180/******************************************************************************/
181/* X r d M p x V a r */
182/******************************************************************************/
183
185{
186public:
187
188 int Pop(const char *vName);
189
190 int Push(const char *vName);
191
192 void Reset() {vEnd = vBuff; vNum = -1; *vBuff = 0;}
193
194const char *Var() {return vBuff;}
195
196 XrdMpxVar(bool dbg=false)
197 : vFence(vBuff + sizeof(vBuff) - 1), Debug(dbg) {Reset();}
199
200private:
201static const int vMax = 15;
202 char *vEnd, *vFence, *vStack[vMax+1], vBuff[1024];
203 int vNum;
204 bool Debug;
205};
206
207/******************************************************************************/
208/* X r d M p x V a r : : P o p */
209/******************************************************************************/
210
211int XrdMpxVar::Pop(const char *vName)
212{
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--;
216 return 1;
217}
218
219/******************************************************************************/
220/* X r d M p x V a r : : P u s h */
221/******************************************************************************/
222
223int XrdMpxVar::Push(const char *vName)
224{
225 int n = strlen(vName);
226
227 if (Debug) std::cerr <<"Push: " <<vName <<"; var=" <<vBuff <<std::endl;
228 if (vNum >= vMax) return 0;
229 if (vNum >= 0) *vEnd++ = '.';
230 else vEnd = vBuff;
231 if (vEnd+n+1 >= vFence) return 0;
232 strcpy(vEnd, vName);
233 vStack[++vNum] = vEnd;
234 vEnd += n;
235 return 1;
236}
237
238/******************************************************************************/
239/* X r d M p x X m l : : F o r m a t */
240/******************************************************************************/
241
242int XrdMpxXml::Format(const char *Host, char *ibuff, char *obuff)
243{
244 static const char *Hdr0 = "<statistics ";
245 static const int H0Len = strlen(Hdr0);
246
247 XrdMpxVar xVar(Debug);
248 XrdOucTokenizer Data(ibuff);
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;
254 int i, rc;
255
256// Insert a newline for the first '>'
257//
258 if (!(lP = (char *)index(lP, '>')))
259 return xmlErr("Invalid xml stream: ", ibuff);
260 *lP++ = '\n';
261
262// Now make the input tokenizable
263//
264 while(*lP)
265 {if (*lP == '>' || (*lP == '<' && *(lP+1) == '/')) *lP = ' ';
266 lP++;
267 }
268
269// The first token better be '<statistics'
270//
271 if (!(lP = Data.GetLine()) || strncmp(Hdr0, lP, H0Len))
272 return xmlErr("Stream does not start with '<statistics'.");
273 Data.GetToken(); getVars(Data, vHead);
274
275// Output the vars in the headers as 'stats..var'
276//
277 for (i = 0; vHead[i].Name; i++)
278 {if (vHead[i].Data) oP = Add(oP, vHead[i].Name, vHead[i].Data);}
279
280// Add in the host name, if supplied
281//
282 if (Host) oP = Add(oP, "host", Host);
283
284// Get the remainder
285//
286 if (!Data.GetLine()) return xmlErr("Null xml stream after header.");
287
288// The following segment reads all of the "stats" entries
289//
290 while((tP = Data.GetToken()) && strcmp(tP, "/statistics"))
291 { if (*tP == '/')
292 {if (!xVar.Pop(strcmp("/stats", tP) ? tP+1 : 0))
293 return xmlErr(tP, "invalid end for ", xVar.Var());
294 }
295 else if (*tP == '<')
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)
299 : xVar.Push(tP+1));
300 }
301 if (!rc) return xmlErr("Nesting too deep for ", xVar.Var());
302 }
303 else {if ((vP = index(tP, '<'))) *vP = '\0';
304 if (*tP == '"')
305 {i = strlen(tP)-1;
306 if (*(tP+i) == '"') {*(tP+i) = '\0'; i = 1;}
307 } else i = 0;
308 oP = Add(oP, xVar.Var(), tP+i);
309 if (vP) {*vP = '<';
310 if (vP != tP) memset(tP, ' ', vP - tP);
311 Data.RetToken();
312 }
313 }
314 }
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--;
319 *oP++ = '\n';
320 return oP - obuff;
321}
322
323/******************************************************************************/
324/* X r d M p x X m l : : A d d */
325/******************************************************************************/
326
327char *XrdMpxXml::Add(char *Buff, const char *Var, const char *Val)
328{
329 char tmBuff[256];
330
331 if (noZed && !strcmp("0", Val)) return Buff;
332
333 if (doV2T)
334 {std::map<const char *, const char *, vCmp>::iterator it;
335 it = vnMap.find(Var);
336 if (it != vnMap.end())
337 {Var = it->second;
338 if (*Var == '~')
339 {time_t tod = atoi(Val);
340 Var++;
341 if (tod)
342 {struct tm *tInfo = localtime(&tod);
343 strftime(tmBuff, sizeof(tmBuff), "%a %F %T", tInfo);
344 Val = tmBuff;
345 }
346 }
347 }
348 }
349
350 strcpy(Buff, Var); Buff += strlen(Var);
351 *Buff++ = vSep;
352 strcpy(Buff, Val); Buff += strlen(Val);
353 *Buff++ = vSfx;
354 return Buff;
355}
356
357/******************************************************************************/
358/* */
359/* X r d M p x X m l : : g e t V a r s */
360/* */
361/******************************************************************************/
362
363void XrdMpxXml::getVars(XrdOucTokenizer &Data, VarInfo Var[])
364{
365 char *tVar, *tVal;
366 int i;
367
368// Initialize the data pointers to null
369//
370 i = 0;
371 while(Var[i].Name) Var[i++].Data = 0;
372
373// Get all of the variables/values and return where possible
374//
375 while((tVar = Data.GetToken()) && *tVar != '<' && *tVar != '/')
376 {if (!(tVal = (char *)index(tVar, '='))) continue;
377 *tVal++ = '\0';
378 if (*tVal == '"')
379 {tVal++, i = strlen(tVal);
380 if (*(tVal+i-1) == '"') *(tVal+i-1) = '\0';
381 }
382 i = 0;
383 while(Var[i].Name)
384 {if (!strcmp(Var[i].Name, tVar)) {Var[i].Data = tVal; break;}
385 else i++;
386 }
387 }
388 if (tVar && (*tVar == '<' || *tVar == '/')) Data.RetToken();
389}
390
391/******************************************************************************/
392/* X r d M p x X m l : : x m l E r r */
393/******************************************************************************/
394
395int XrdMpxXml::xmlErr(const char *t1, const char *t2, const char *t3)
396{
397 std::cerr <<"XrdMpxXml: " <<t1 <<' ' <<t2 <<' ' <<t3 <<std::endl;
398 return 0;
399}
int Push(const char *vName)
Definition XrdMpxXml.cc:223
const char * Var()
Definition XrdMpxXml.cc:194
void Reset()
Definition XrdMpxXml.cc:192
XrdMpxVar(bool dbg=false)
Definition XrdMpxXml.cc:196
int Pop(const char *vName)
Definition XrdMpxXml.cc:211
int Format(const char *Host, char *ibuff, char *obuff)
Definition XrdMpxXml.cc:242
char * GetToken(char **rest=0, int lowcase=0)