00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
00044
00045
00046 XrdCnsLogFile::~XrdCnsLogFile()
00047 {
00048
00049
00050 synSem.Wait();
00051
00052
00053
00054 if (logFD >= 0) close(logFD);
00055 if (logFN) free(logFN);
00056 if (logBuff) free(logBuff);
00057 }
00058
00059
00060
00061
00062
00063 int XrdCnsLogFile::Add(XrdCnsLogRec *lrP, int doSync)
00064 {
00065 XrdCnsLogFile *lfP = subNext;
00066 char *bP;
00067 int rc, bL;
00068
00069
00070
00071 bL = lrP->setLen() + XrdCnsLogRec::MinSize;
00072 bP = lrP->Record();
00073
00074
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
00084
00085 if (doSync && fdatasync(logFD)) MLog.Emsg("Add", errno, "fsync log", logFN);
00086
00087
00088
00089 while(lfP) {lfP->logSem.Post(); lfP = lfP->subNext;}
00090
00091
00092
00093 return 1;
00094 }
00095
00096
00097
00098
00099
00100 int XrdCnsLogFile::Commit()
00101 {
00102 static char dVal = 1;
00103 int dOffs, rc;
00104
00105
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
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
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
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
00150
00151 return 1;
00152 }
00153
00154
00155
00156
00157
00158 XrdCnsLogRec *XrdCnsLogFile::getRec()
00159 {
00160 char *bP, *nP;
00161 int bL;
00162
00163
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
00188
00189 return (Rec.L1sz() ? &Rec : 0);
00190 }
00191
00192
00193
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
00201
00202 if ((logFD = open(logFN, O_CREAT|O_RDWR, AMode)) < 0)
00203 {MLog.Emsg("Open", errno, "open", logFN); return 0;}
00204
00205
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
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
00221
00222 return 1;
00223 }
00224
00225
00226
00227
00228
00229 int XrdCnsLogFile::Read(char *bP, int bL)
00230 {
00231 int rc;
00232
00233
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
00241
00242 return 1;
00243 }
00244
00245
00246
00247
00248
00249 XrdCnsLogFile *XrdCnsLogFile::Subscribe(const char *Path, int cNum)
00250 {
00251 XrdCnsLogFile *lfP;
00252 int rc;
00253
00254
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
00262
00263 lfP = new XrdCnsLogFile(Path, cNum);
00264 lfP->logWait = 1;
00265 lfP->synSem.Wait();
00266
00267
00268
00269 lfP->subNext = subNext;
00270 subNext = lfP;
00271 return lfP;
00272 }
00273
00274
00275
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 }