XRootD
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 
48 namespace
49 {
50 struct vCmp
51  {bool operator()(const char *a, const char *b)
52  const {return strcmp(a,b) < 0;}
53  };
54 
55 std::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 {
186 public:
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 
194 const char *Var() {return vBuff;}
195 
196  XrdMpxVar(bool dbg=false)
197  : vFence(vBuff + sizeof(vBuff) - 1), Debug(dbg) {Reset();}
199 
200 private:
201 static 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 
211 int 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 
223 int 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 
242 int 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 
327 char *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 
363 void 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 
395 int 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
void Reset()
Definition: XrdMpxXml.cc:192
const char * Var()
Definition: XrdMpxXml.cc:194
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)