00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdStatsCVSID = "$Id: XrdStats.cc 34000 2010-06-21 06:49:56Z ganis $";
00014
00015 #if !defined(__macos__) && !defined(__FreeBSD__)
00016 #include <malloc.h>
00017 #endif
00018 #include <stdio.h>
00019 #include <sys/time.h>
00020 #include <sys/resource.h>
00021
00022 #include "XrdVersion.hh"
00023 #include "Xrd/XrdBuffer.hh"
00024 #include "Xrd/XrdJob.hh"
00025 #include "Xrd/XrdLink.hh"
00026 #include "Xrd/XrdPoll.hh"
00027 #include "Xrd/XrdProtLoad.hh"
00028 #include "Xrd/XrdScheduler.hh"
00029 #include "Xrd/XrdStats.hh"
00030 #include "XrdNet/XrdNetMsg.hh"
00031 #include "XrdSys/XrdSysPlatform.hh"
00032 #include "XrdSys/XrdSysTimer.hh"
00033
00034
00035
00036
00037
00038 extern XrdBuffManager XrdBuffPool;
00039
00040 extern XrdScheduler XrdSched;
00041
00042 long XrdStats::tBoot = static_cast<long>(time(0));
00043
00044
00045
00046
00047
00048 class XrdStatsJob : XrdJob
00049 {
00050 public:
00051
00052 void DoIt() {Stats->Report();
00053 XrdSched.Schedule((XrdJob *)this, time(0)+iVal);
00054 }
00055
00056 XrdStatsJob(XrdStats *sP, int iV) : XrdJob("stats reporter"),
00057 Stats(sP), iVal(iV)
00058 {XrdSched.Schedule((XrdJob *)this, time(0)+iVal);}
00059 ~XrdStatsJob() {}
00060 private:
00061 XrdStats *Stats;
00062 int iVal;
00063 };
00064
00065
00066
00067
00068
00069 XrdStats::XrdStats(const char *hname, int port,
00070 const char *iname, const char *pname)
00071 {
00072 static const char *head =
00073 "<statistics tod=\"%%ld\" ver=\"" XrdVSTRING "\" src=\"%s:%d\" "
00074 "tos=\"%ld\" pgm=\"%s\" ins=\"%s\" pid=\"%d\">";
00075 char myBuff[1024];
00076
00077 Hlen = sprintf(myBuff, head, hname, port, tBoot, pname, iname,
00078 static_cast<int>(getpid()));
00079 Head = strdup(myBuff);
00080 buff = 0;
00081 blen = 0;
00082 myHost = hname;
00083 myName = iname;
00084 myPort = port;
00085 }
00086
00087
00088
00089
00090
00091 void XrdStats::Report(char **Dest, int iVal, int Opts)
00092 {
00093 extern XrdSysError XrdLog;
00094 static XrdNetMsg *netDest[2] = {0,0};
00095 static int autoSync, repOpts = Opts;
00096 XrdJob *jP;
00097 const char *Data;
00098 int theOpts, Dlen;
00099
00100
00101
00102 if (Dest)
00103
00104
00105 {if (Dest[0]) netDest[0] = new XrdNetMsg(&XrdLog, Dest[0]);
00106 if (Dest[1]) netDest[1] = new XrdNetMsg(&XrdLog, Dest[1]);
00107 if (!(repOpts & XRD_STATS_ALL)) repOpts |= XRD_STATS_ALL;
00108 autoSync = repOpts & XRD_STATS_SYNCA;
00109
00110
00111
00112 if (netDest[0]) jP = (XrdJob *)new XrdStatsJob(this, iVal);
00113 return;
00114 }
00115
00116
00117
00118 if (!autoSync || XrdSched.Active() <= 30) theOpts = repOpts;
00119 else theOpts = repOpts & ~XRD_STATS_SYNC;
00120
00121
00122
00123 Lock();
00124 if ((Data = Stats(theOpts)))
00125 {Dlen = strlen(Data);
00126 netDest[0]->Send(Data, Dlen);
00127 if (netDest[1]) netDest[1]->Send(Data, Dlen);
00128 }
00129 UnLock();
00130 }
00131
00132
00133
00134
00135
00136 const char *XrdStats::Stats(int opts)
00137 {
00138 static const char *sgen = "<stats id=\"sgen\">"
00139 "<as>%d</as><et>%lu</et><toe>%ld</toe></stats>";
00140 static const char *tail = "</statistics>";
00141 static const char *snul = "<statistics tod=\"0\" ver=\"" XrdVSTRING "\">"
00142 "</statistics>";
00143
00144 static XrdProtLoad Protocols;
00145 static const int ovrhed = 256+strlen(sgen)+strlen(tail);
00146 XrdSysTimer myTimer;
00147 char *bp;
00148 int bl, sz, do_sync = (opts & XRD_STATS_SYNC ? 1 : 0);
00149
00150
00151
00152
00153 if (!(bp = buff))
00154 {blen = InfoStats(0,0) + XrdBuffPool.Stats(0,0) + XrdLink::Stats(0,0)
00155 + ProcStats(0,0) + XrdSched.Stats(0,0) + XrdPoll::Stats(0,0)
00156 + Protocols.Stats(0,0) + ovrhed + Hlen;
00157 buff = (char *)memalign(getpagesize(), blen+256);
00158 if (!(bp = buff)) return snul;
00159 }
00160 bl = blen;
00161
00162
00163
00164 if (opts & XRD_STATS_SGEN) myTimer.Reset();
00165
00166
00167
00168 sz = sprintf(buff, Head, static_cast<long>(time(0)));
00169 bl -= sz; bp += sz;
00170
00171
00172
00173 if (opts & XRD_STATS_INFO)
00174 {sz = InfoStats(bp, bl, do_sync);
00175 bp += sz; bl -= sz;
00176 }
00177
00178 if (opts & XRD_STATS_BUFF)
00179 {sz = XrdBuffPool.Stats(bp, bl, do_sync);
00180 bp += sz; bl -= sz;
00181 }
00182
00183 if (opts & XRD_STATS_LINK)
00184 {sz = XrdLink::Stats(bp, bl, do_sync);
00185 bp += sz; bl -= sz;
00186 }
00187
00188 if (opts & XRD_STATS_POLL)
00189 {sz = XrdPoll::Stats(bp, bl, do_sync);
00190 bp += sz; bl -= sz;
00191 }
00192
00193 if (opts & XRD_STATS_PROC)
00194 {sz = ProcStats(bp, bl, do_sync);
00195 bp += sz; bl -= sz;
00196 }
00197
00198 if (opts & XRD_STATS_PROT)
00199 {sz = Protocols.Stats(bp, bl, do_sync);
00200 bp += sz; bl -= sz;
00201 }
00202
00203 if (opts & XRD_STATS_SCHD)
00204 {sz = XrdSched.Stats(bp, bl, do_sync);
00205 bp += sz; bl -= sz;
00206 }
00207
00208 if (opts & XRD_STATS_SGEN)
00209 {unsigned long totTime = 0;
00210 myTimer.Report(totTime);
00211 sz = snprintf(bp,bl,sgen,do_sync==0,totTime,static_cast<long>(time(0)));
00212 bp += sz; bl -= sz;
00213 }
00214
00215 strlcpy(bp, tail, bl);
00216 return buff;
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226 int XrdStats::InfoStats(char *bfr, int bln, int do_sync)
00227 {
00228 static const char statfmt[] = "<stats id=\"info\"><host>%s</host>"
00229 "<port>%d</port><name>%s</name></stats>";
00230
00231
00232
00233 if (!bfr) return sizeof(statfmt)+24 + strlen(myHost);
00234
00235
00236
00237 return snprintf(bfr, bln, statfmt, myHost, myPort, myName);
00238 }
00239
00240
00241
00242
00243
00244 int XrdStats::ProcStats(char *bfr, int bln, int do_sync)
00245 {
00246 static const char statfmt[] = "<stats id=\"proc\">"
00247 "<usr><s>%lld</s><u>%lld</u></usr>"
00248 "<sys><s>%lld</s><u>%lld</u></sys>"
00249 "</stats>";
00250 struct rusage r_usage;
00251 long long utime_sec, utime_usec, stime_sec, stime_usec;
00252
00253
00254
00255
00256
00257 if (!bfr) return sizeof(statfmt)+16*13;
00258
00259
00260
00261 if (getrusage(RUSAGE_SELF, &r_usage)) return 0;
00262
00263
00264
00265
00266
00267
00268 utime_sec = static_cast<long long>(r_usage.ru_utime.tv_sec);
00269 utime_usec = static_cast<long long>(r_usage.ru_utime.tv_usec);
00270 stime_sec = static_cast<long long>(r_usage.ru_stime.tv_sec);
00271 stime_usec = static_cast<long long>(r_usage.ru_stime.tv_usec);
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 return snprintf(bfr, bln, statfmt,
00284 utime_sec, utime_usec, stime_sec, stime_usec
00285
00286
00287 );
00288 }