XrdCnsLogFile.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                      X r d C n s L o g F i l e . 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: XrdCnsLogFile.cc 34000 2010-06-21 06:49:56Z ganis $
00012 
00013 const char *XrdCnsLogFileCVSID = "$Id: XrdCnsLogFile.cc 34000 2010-06-21 06:49:56Z ganis $";
00014 
00015 #include <fcntl.h>
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #include <sys/stat.h>
00021 #include <sys/types.h>
00022 #include <time.h>
00023 
00024 #include "XrdCns/XrdCnsLogFile.hh"
00025 #include "XrdSys/XrdSysError.hh"
00026 #include "XrdSys/XrdSysPlatform.hh"
00027 
00028 /******************************************************************************/
00029 /*                               G l o b a l s                                */
00030 /******************************************************************************/
00031   
00032 int XrdCnsLogFile::logRMax = 1024;
00033 int XrdCnsLogFile::logBMax = 1024 * sizeof(XrdCnsLogRec);
00034 
00035 namespace XrdCns
00036 {
00037 extern XrdSysError MLog;
00038 }
00039 
00040 using namespace XrdCns;
00041   
00042 /******************************************************************************/
00043 /*                            D e s t r u c t o r                             */
00044 /******************************************************************************/
00045 
00046 XrdCnsLogFile::~XrdCnsLogFile()
00047 {
00048 // Wait until it is safe to delete ourselves
00049 //
00050    synSem.Wait();
00051 
00052 // Do clean-up
00053 //
00054    if (logFD >= 0) close(logFD);
00055    if (logFN)      free(logFN);
00056    if (logBuff)    free(logBuff);
00057 }
00058 
00059 /******************************************************************************/
00060 /*                                   A d d                                    */
00061 /******************************************************************************/
00062   
00063 int XrdCnsLogFile::Add(XrdCnsLogRec *lrP, int doSync)
00064 {
00065    XrdCnsLogFile *lfP = subNext;
00066    char *bP;
00067    int   rc, bL;
00068 
00069 // Compute full record length
00070 //
00071    bL = lrP->setLen() + XrdCnsLogRec::MinSize;
00072    bP = lrP->Record();
00073 
00074 // Write out record
00075 //
00076    do {do {rc = write(logFD, bP, bL);} while (rc < 0 && errno == EINTR);
00077        if (rc < 0) {MLog.Emsg("Add", errno, "add log rec to", logFN);
00078                     return 0;
00079                    }
00080        bP += rc; bL -= rc;
00081       } while(bL > 0);
00082 
00083 // Make sure data is on disk
00084 //
00085    if (doSync && fdatasync(logFD)) MLog.Emsg("Add", errno, "fsync log", logFN);
00086 
00087 // Notify all subscribers
00088 //
00089    while(lfP) {lfP->logSem.Post(); lfP = lfP->subNext;}
00090 
00091 // All done
00092 //
00093    return 1;
00094 }
00095 
00096 /******************************************************************************/
00097 /*                                C o m m i t                                 */
00098 /******************************************************************************/
00099   
00100 int XrdCnsLogFile::Commit()
00101 {
00102    static char dVal = 1;
00103    int dOffs, rc;
00104 
00105 // Commit the previous record if we have returned one
00106 //
00107    if (logOffset)
00108       {Rec.setDone(logRdr);
00109        dOffs = recOffset + XrdCnsLogRec::OffDone + logRdr;
00110        do {rc=pwrite(logFD, &dVal, 1, dOffs);} while(rc < 0 && errno == EINTR);
00111        if (rc > 0) fdatasync(logFD);
00112           else {MLog.Emsg("Commit", errno, "commit log rec in", logFN);
00113                 return 0;
00114                }
00115       }
00116    return 1;
00117 }
00118 
00119 /******************************************************************************/
00120 /*                                   E o l                                    */
00121 /******************************************************************************/
00122   
00123 int XrdCnsLogFile::Eol()
00124 {
00125    XrdCnsLogFile *lfX, *lfP = subNext;
00126    XrdCnsLogRec   lRec(XrdCnsLogRec::lrEOL);
00127    int rc, bL = XrdCnsLogRec::MinSize + lRec.DLen();
00128    char *bP = (char *)&lRec;
00129 
00130 // Write out record end of log record
00131 //
00132    do {do {rc = write(logFD, bP, bL);} while (rc < 0 && errno == EINTR);
00133        if (rc < 0) {MLog.Emsg("Eol", errno, "eol log file", logFN);
00134                     break;
00135                    }
00136        bP += rc; bL -= rc;
00137       } while(bL > 0);
00138 
00139 // Allow subscribers to end
00140 //
00141    while(lfP)
00142         {lfP->logSem.Post();
00143          lfP->logWait = 0;
00144          lfX = lfP;
00145          lfP = lfP->subNext;
00146          lfX->synSem.Post();
00147         }
00148 
00149 // All done
00150 //
00151    return 1;
00152 }
00153 
00154 /******************************************************************************/
00155 /*                                g e t R e c                                 */
00156 /******************************************************************************/
00157   
00158 XrdCnsLogRec *XrdCnsLogFile::getRec()
00159 {
00160    char *bP, *nP;
00161    int   bL;
00162 
00163 // Wait for a record if we must wait, read it, return if it's not committed
00164 //
00165    do {if (logWait) logSem.Wait();
00166        bP = Rec.Record();
00167        bL = XrdCnsLogRec::MinSize; recOffset = logOffset;
00168 
00169        if (!Read(bP, bL) || !((bL = Rec.DLen()))) return 0;
00170        if (bL < XrdCnsLogRec::FixDLen)
00171           {MLog.Emsg("getRec", "Invalid record length detected in", logFN);
00172            return 0;
00173           }
00174 
00175        bP = bP + XrdCnsLogRec::MinSize;
00176        if (!Read(bP, bL)) return 0;
00177 
00178        memcpy(logNext, bP, bL);
00179        nP = logNext + XrdCnsLogRec::FixDLen + Rec.L1sz();
00180        if (!Rec.L2sz()) *nP = '\n';
00181           else {*nP = ' ';
00182                 *(nP + Rec.L2sz() + 1) = '\n';
00183                }
00184        logNext += bL;
00185       } while(Rec.Done(logRdr));
00186 
00187 // Return the record or nil pointer if there is no associated file
00188 //
00189    return (Rec.L1sz() ? &Rec : 0);
00190 }
00191 
00192 /******************************************************************************/
00193 /*                                  O p e n                                   */
00194 /******************************************************************************/
00195   
00196 int XrdCnsLogFile::Open(int allocbuff, off_t thePos)
00197 {
00198    static const int AMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00199 
00200 // Open the file
00201 //
00202    if ((logFD = open(logFN, O_CREAT|O_RDWR, AMode)) < 0)
00203       {MLog.Emsg("Open", errno, "open", logFN); return 0;}
00204 
00205 // Set starting position if need be
00206 //
00207    if (thePos && (lseek(logFD, thePos, SEEK_SET) == (off_t)-1))
00208       {MLog.Emsg("Open", errno, "seek into", logFN); close(logFD), logFD = -1;
00209        return 0;
00210       }
00211 
00212 // Allocate a memory buffer if so wanted
00213 //
00214    if (allocbuff)
00215       {struct stat Stat;
00216        if (fstat(logFD, &Stat)) MLog.Emsg("Open", errno, "stat", logFN);
00217           else logNext=logBuff=(char *)malloc(logWait ? logBMax : Stat.st_size);
00218       }
00219 
00220 // All done
00221 //
00222    return 1;
00223 }
00224 
00225 /******************************************************************************/
00226 /* Private:                         R e a d                                   */
00227 /******************************************************************************/
00228   
00229 int XrdCnsLogFile::Read(char *bP, int bL)
00230 {
00231    int rc;
00232 
00233 // Read the data
00234 //
00235    do{do {rc = pread(logFD,bP,bL,logOffset);} while(rc < 0 && errno == EINTR);
00236       if (rc < 0) {MLog.Emsg("getRec", errno, "read", logFN); return 0;}
00237       bP += rc; bL -= rc; logOffset += rc;
00238      } while(bL > 0);
00239 
00240 // All done
00241 //
00242    return 1;
00243 }
00244 
00245 /******************************************************************************/
00246 /*                             S u b s c r i b e                              */
00247 /******************************************************************************/
00248   
00249 XrdCnsLogFile *XrdCnsLogFile::Subscribe(const char *Path, int cNum)
00250 {
00251    XrdCnsLogFile *lfP;
00252    int rc;
00253 
00254 // Create hard link to our log file
00255 //
00256    do {rc = link(logFN, Path);} while(rc && errno == EINTR);
00257    if (rc) {MLog.Emsg("Subscribe", errno, "create hard link", Path);
00258             return 0;
00259            }
00260 
00261 // Indicate wait is needed and that delete must wait as well
00262 //
00263    lfP = new XrdCnsLogFile(Path, cNum);
00264    lfP->logWait = 1;
00265    lfP->synSem.Wait();
00266 
00267 // Chain in the subscriber
00268 //
00269    lfP->subNext = subNext;
00270    subNext = lfP;
00271    return lfP;
00272 }
00273 
00274 /******************************************************************************/
00275 /*                                U n l i n k                                 */
00276 /******************************************************************************/
00277   
00278 int XrdCnsLogFile::Unlink()
00279 {
00280    int rc;
00281 
00282    do {rc = unlink(logFN);} while(rc < 0 && errno == EINTR);
00283    if (rc < 0) MLog.Emsg("Unlink", errno, "remove log", logFN);
00284    return rc >= 0;
00285 }

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