XrdBwmLogger.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d B w m L o g g e r . c c                        */
00004 /*                                                                            */
00005 /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010   
00011 //         $Id: XrdBwmLogger.cc 30949 2009-11-02 16:37:58Z ganis $
00012 
00013 const char *XrdBwmLoggerCVSID = "$Id: XrdBwmLogger.cc 30949 2009-11-02 16:37:58Z ganis $";
00014 
00015 #include <ctype.h>
00016 #include <stddef.h>
00017 #include <stdlib.h>
00018 #include <stdio.h>
00019 #include <string.h>
00020 
00021 #include "XrdBwm/XrdBwmLogger.hh"
00022 #include "XrdSys/XrdSysError.hh"
00023 #include "XrdOuc/XrdOucProg.hh"
00024 #include "XrdOuc/XrdOucStream.hh"
00025 #include "XrdNet/XrdNetOpts.hh"
00026 #include "XrdNet/XrdNetSocket.hh"
00027 #include "XrdSys/XrdSysPlatform.hh"
00028 
00029 /******************************************************************************/
00030 /*                         L o c a l   C l a s s e s                          */
00031 /******************************************************************************/
00032 
00033 class XrdBwmLoggerMsg
00034 {
00035 public:
00036 
00037 static const int msgSize = 2048;
00038 
00039 XrdBwmLoggerMsg *next;
00040 char             Text[msgSize];
00041 int              Tlen;
00042 
00043              XrdBwmLoggerMsg() : next(0), Tlen(0) {}
00044 
00045             ~XrdBwmLoggerMsg() {}
00046 };
00047 
00048 /******************************************************************************/
00049 /*                     E x t e r n a l   L i n k a g e s                      */
00050 /******************************************************************************/
00051   
00052 void *XrdBwmLoggerSend(void *pp)
00053 {
00054      XrdBwmLogger *lP = (XrdBwmLogger *)pp;
00055      lP->sendEvents();
00056      return (void *)0;
00057 }
00058 
00059 /******************************************************************************/
00060 /*                           C o n s t r u c t o r                            */
00061 /******************************************************************************/
00062   
00063 XrdBwmLogger::XrdBwmLogger(const char *Target)
00064 {
00065 
00066 // Set common variables
00067 //
00068    theTarget = strdup(Target);
00069    eDest = 0; 
00070    theProg = 0;
00071    msgFirst = msgLast = msgFree = 0;
00072    tid = 0;
00073    msgFD = 0;
00074    endIT = 0;
00075    theEOL= '\n';
00076 }
00077 
00078 /******************************************************************************/
00079 /*                            D e s t r u c t o r                             */
00080 /******************************************************************************/
00081 
00082 XrdBwmLogger::~XrdBwmLogger()
00083 {
00084   XrdBwmLoggerMsg *tp;
00085 
00086 // Kill the notification thread. This may cause a msg block to be orphaned
00087 // but, in practice, this object does not really get deleted after being 
00088 // started. So, the problem is moot.
00089 //
00090    endIT = 1;
00091    if (tid) XrdSysThread::Kill(tid);
00092 
00093 // Release all queued message bocks
00094 //
00095   qMut.Lock();
00096   while ((tp = msgFirst)) {msgFirst = tp->next; delete tp;}
00097   if (theTarget)  free(theTarget);
00098   if (msgFD >= 0) close(msgFD);
00099   if (theProg)    delete theProg;
00100   qMut.UnLock();
00101 
00102 // Release all free message blocks
00103 //
00104   fMut.Lock();
00105   while ((tp = msgFree)) {msgFree = tp->next; delete tp;}
00106   fMut.UnLock();
00107 }
00108 
00109 /******************************************************************************/
00110 /*                                 E v e n t                                  */
00111 /******************************************************************************/
00112   
00113 void XrdBwmLogger::Event(Info &eInfo)
00114 {
00115    static int warnings = 0;
00116    XrdBwmLoggerMsg *tp;
00117 
00118 // Get a message block
00119 //
00120    if (!(tp = getMsg()))
00121       {if ((++warnings & 0xff) == 1)
00122           eDest->Emsg("Notify", "Ran out of logger message objects;",
00123                                 eInfo.Tident, "event not logged.");
00124           return;
00125       }
00126 
00127 // Format the message
00128 //
00129    tp->Tlen = snprintf(tp->Text, XrdBwmLoggerMsg::msgSize,
00130                     "<stats id=\"bwm\"><tid>%s</tid><lfn>%s</lfn>"
00131                     "<lcl>%s</lcl><rmt>%s</rmt><flow>%c</flow>"
00132                     "<at>%ld</at><bt>%ld</bt><ct>%ld</ct>"
00133                     "<iq>%d</iq><oq>%d</oq><xq>%d</xq>"
00134                     "<sz>%lld<sz><esec>%d</esec></stats>%c",
00135                     eInfo.Tident, eInfo.Lfn, eInfo.lclNode, eInfo.rmtNode,
00136                     eInfo.Flow, eInfo.ATime, eInfo.BTime, eInfo.CTime,
00137                     eInfo.numqIn, eInfo.numqOut, eInfo.numqXeq, eInfo.Size,
00138                     eInfo.ESec, theEOL);
00139 
00140 // Either log this or put the message on the queue and return
00141 //
00142    tp->next = 0;
00143    qMut.Lock();
00144    if (msgLast) {msgLast->next = tp; msgLast = tp;}
00145       else msgFirst = msgLast = tp;
00146    qMut.UnLock();
00147    qSem.Post();
00148 }
00149 
00150 /******************************************************************************/
00151 /*                            s e n d E v e n t s                             */
00152 /******************************************************************************/
00153   
00154 void XrdBwmLogger::sendEvents(void)
00155 {
00156    XrdBwmLoggerMsg *tp;
00157    const char *theData[2] = {0,0};
00158          int   theDlen[2] = {0,0};
00159 
00160 // This is an endless loop that just gets things off the event queue and
00161 // send them out. This allows us to only hang a simgle thread should the
00162 // receiver get blocked, instead of the whole process.
00163 //
00164    while(1)
00165         {qSem.Wait();
00166          qMut.Lock();
00167          if (endIT) break;
00168          if ((tp = msgFirst) && !(msgFirst = tp->next)) msgLast = 0;
00169          qMut.UnLock();
00170          if (tp) 
00171             {if (!theProg) Feed(tp->Text, tp->Tlen);
00172                 else {theData[0] = tp->Text; theDlen[0] = tp->Tlen;
00173                       theProg->Feed(theData, theDlen);
00174 
00175                      }
00176              retMsg(tp);
00177             }
00178          }
00179    qMut.UnLock();
00180 }
00181 
00182 /******************************************************************************/
00183 /*                                 S t a r t                                  */
00184 /******************************************************************************/
00185   
00186 int XrdBwmLogger::Start(XrdSysError *eobj)
00187 {
00188    int rc;
00189 
00190 // Set the error object pointer
00191 //
00192    eDest = eobj;
00193 
00194 // Check if we need to create a socket to a path
00195 //
00196         if (!strcmp("*", theTarget)) {msgFD = -1; theEOL = '\0';}
00197    else if (*theTarget == '>')
00198            {XrdNetSocket *msgSock;
00199             if (!(msgSock = XrdNetSocket::Create(eobj, theTarget+1, 0, 0660,
00200                                                  XRDNET_FIFO))) return -1;
00201             msgFD = msgSock->Detach();
00202             delete msgSock;
00203            }
00204    else    {// Allocate a new program object if we don't have one
00205             //
00206             if (theProg) return 0;
00207             theProg = new XrdOucProg(eobj);
00208 
00209             // Setup the program
00210             //
00211             if (theProg->Setup(theTarget, eobj)) return -1;
00212             if ((rc = theProg->Start()))
00213                {eobj->Emsg("Logger", rc, "start event collector"); return -1;}
00214            }
00215 
00216 // Now start a thread to get messages and send them to the collector
00217 //
00218    if ((rc = XrdSysThread::Run(&tid, XrdBwmLoggerSend, static_cast<void *>(this),
00219                           0, "Log message sender")))
00220       {eobj->Emsg("Logger", rc, "create log message sender thread");
00221        return -1;
00222       }
00223 
00224 // All done
00225 //
00226    return 0;
00227 }
00228 
00229 /******************************************************************************/
00230 /*                       P r i v a t e   M e t h o d s                        */
00231 /******************************************************************************/
00232 /******************************************************************************/
00233 /*                                  F e e d                                   */
00234 /******************************************************************************/
00235   
00236 int XrdBwmLogger::Feed(const char *data, int dlen)
00237 {
00238    int retc;
00239 
00240 // Send message to the log if need be
00241 //
00242    if (msgFD < 0) {eDest->Say("", data); return 0;}
00243 
00244 // Write the data. since this is a udp socket all the data goes or none does
00245 //
00246   do { retc = write(msgFD, (const void *)data, (size_t)dlen);}
00247        while (retc < 0 && errno == EINTR);
00248   if (retc < 0)
00249      {eDest->Emsg("Feed", errno, "write to logger socket", theTarget);
00250       return -1;
00251      }
00252 
00253 // All done
00254 //
00255    return 0;
00256 }
00257 
00258 /******************************************************************************/
00259 /*                                g e t M s g                                 */
00260 /******************************************************************************/
00261 
00262 XrdBwmLoggerMsg *XrdBwmLogger::getMsg()
00263 {
00264    XrdBwmLoggerMsg *tp;
00265 
00266 // Lock the free queue
00267 //
00268    fMut.Lock();
00269 
00270 // Get message object but don't give out too many
00271 //
00272    if (msgsInQ >= maxmInQ) tp = 0;
00273       else {if ((tp = msgFree)) msgFree = tp->next;
00274                else tp = new XrdBwmLoggerMsg();
00275             msgsInQ++;
00276            }
00277 
00278 // Unlock and return result
00279 //
00280    fMut.UnLock();
00281    return tp;
00282 }
00283 
00284 /******************************************************************************/
00285 /*                                r e t M s g                                 */
00286 /******************************************************************************/
00287 
00288 void XrdBwmLogger::retMsg(XrdBwmLoggerMsg *tp)
00289 {
00290 
00291 // Lock the free queue, return message, unlock the queue
00292 //
00293    fMut.Lock();
00294    tp->next = msgFree; 
00295    msgFree  = tp;
00296    msgsInQ--;
00297    fMut.UnLock();
00298 }

Generated on Tue Jul 5 14:46:16 2011 for ROOT_528-00b_version by  doxygen 1.5.1