00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 const char *XrdCnsSsiCVSID = "$Id: XrdCnsSsi.cc 34000 2010-06-21 06:49:56Z ganis $";
00014
00015 #include <unistd.h>
00016 #include <string.h>
00017 #include <stdio.h>
00018 #include <time.h>
00019 #include <sys/types.h>
00020 #include <sys/uio.h>
00021
00022 #include "XrdOuc/XrdOucHash.hh"
00023 #include "XrdOuc/XrdOucNSWalk.hh"
00024 #include "XrdOuc/XrdOucSxeq.hh"
00025 #include "XrdOuc/XrdOucStream.hh"
00026 #include "XrdOuc/XrdOucTList.hh"
00027 #include "XrdOuc/XrdOucUtils.hh"
00028
00029 #include "XrdSys/XrdSysError.hh"
00030 #include "XrdSys/XrdSysHeaders.hh"
00031
00032 #include "XrdCns/XrdCnsLog.hh"
00033 #include "XrdCns/XrdCnsSsi.hh"
00034 #include "XrdCns/XrdCnsSsiCfg.hh"
00035 #include "XrdCns/XrdCnsSsiSay.hh"
00036 #include "XrdCns/XrdCnsXref.hh"
00037 #include "XrdCns/XrdCnsLogRec.hh"
00038
00039
00040
00041
00042
00043 struct XrdCnsSsiFRec
00044 {
00045 char Info[XrdCnsLogRec::FixDLen];
00046
00047 void Updt(const char *nInfo) {strncpy(Info, nInfo, sizeof(Info));}
00048
00049 XrdCnsSsiFRec(const char *Data) {if (!Data) Data = XrdCnsLogRec::iArg;
00050 strncpy(Info, Data, sizeof(Info));
00051 *Info = 'i';
00052 }
00053 ~XrdCnsSsiFRec() {}
00054 };
00055
00056 struct XrdCnsSsiDRec
00057 {
00058 XrdOucHash<XrdCnsSsiFRec> *Files;
00059 char Info[XrdCnsLogRec::FixDLen];
00060
00061 XrdCnsSsiDRec(const char *Data) {if (!Data) Data = XrdCnsLogRec::IArg;
00062 strncpy(Info, Data, sizeof(Info));
00063 *Info = 'I';
00064 Files = new XrdOucHash<XrdCnsSsiFRec>;
00065 }
00066 ~XrdCnsSsiDRec() {if (Files) delete Files;}
00067 };
00068
00069
00070
00071
00072
00073 namespace XrdCns
00074 {
00075 extern XrdCnsSsiCfg Config;
00076
00077 extern XrdSysError MLog;
00078
00079 extern XrdCnsSsiSay Say;
00080
00081 XrdOucHash<XrdCnsSsiDRec> *hInv;
00082 XrdCnsXref *mountP;
00083 XrdCnsXref *spaceP;
00084 }
00085
00086 int XrdCnsSsi::nErrs = 0;
00087 int XrdCnsSsi::nDirs = 0;
00088 int XrdCnsSsi::nFiles= 0;
00089
00090 using namespace XrdCns;
00091
00092
00093
00094
00095
00096 int XrdCnsSsiApplyF(const char *Path, XrdCnsSsiFRec *fP, void *Arg)
00097 {
00098 static struct iovec iov[3] = {{0,sizeof(fP->Info)},{0,0},{(char *)"\n",1}};
00099 int n, iFD = *(int *)Arg;
00100
00101 iov[0].iov_base = (char *)fP->Info;
00102 iov[1].iov_base = (char *)Path; n = strlen(Path);
00103 iov[1].iov_len = n;
00104 XrdCnsSsi::nFiles++;
00105
00106 return !XrdCnsSsi::Write(iFD, iov, 3, sizeof(fP->Info)+n+1);
00107 }
00108
00109 int XrdCnsSsiApplyD(const char *Path, XrdCnsSsiDRec *dP, void *Arg)
00110 {
00111 static struct iovec iov[3] = {{0,sizeof(dP->Info)},{0,0},{(char *)"\n",1}};
00112 int n, iFD = *(int *)Arg;
00113
00114
00115
00116 if (dP->Files->Num() <= 0) return 0;
00117
00118
00119
00120 iov[0].iov_base = (char *)dP->Info;
00121 iov[1].iov_base = (char *)Path; n = strlen(Path);
00122 iov[1].iov_len = n;
00123 XrdCnsSsi::nDirs++;
00124
00125 if (!XrdCnsSsi::Write(iFD, iov, 3, sizeof(dP->Info)+n+1)) return 1;
00126
00127
00128
00129 return (dP->Files->Apply(XrdCnsSsiApplyF, Arg) ? 1 : 0);
00130 }
00131
00132 int XrdCnsSsiApplyM(const char *Mount, char *xP, void *Arg)
00133 {
00134 static char Hdr[XrdCnsLogRec::FixDLen];
00135 static XrdCnsLogRec::Arg *aP = (XrdCnsLogRec::Arg *)Hdr;
00136 static struct iovec iov[3] = {{Hdr,sizeof(Hdr)},{0,0},{(char *)"\n",1}};
00137 static int doInit = 1;
00138 int n, iFD = *(int *)Arg;
00139
00140
00141
00142 if (doInit)
00143 {memset(Hdr, ' ', sizeof(Hdr));
00144 aP->Type = XrdCnsLogRec::lrMount;
00145 doInit = 0;
00146 }
00147
00148
00149
00150 aP->Mount = *xP;
00151 iov[1].iov_base = (char *)Mount; n = strlen(Mount);
00152 iov[1].iov_len = n;
00153
00154 return !XrdCnsSsi::Write(iFD, iov, 3, sizeof(Hdr)+n+1);
00155 }
00156
00157 int XrdCnsSsiApplyS(const char *Space, char *xP, void *Arg)
00158 {
00159 static char Hdr[XrdCnsLogRec::FixDLen];
00160 static XrdCnsLogRec::Arg *aP = (XrdCnsLogRec::Arg *)Hdr;
00161 static struct iovec iov[3] = {{Hdr,sizeof(Hdr)},{0,0},{(char *)"\n",1}};
00162 static int doInit = 1;
00163 int n, iFD = *(int *)Arg;
00164
00165
00166
00167 if (doInit)
00168 {memset(Hdr, ' ', sizeof(Hdr));
00169 aP->Type = XrdCnsLogRec::lrSpace;
00170 doInit = 0;
00171 }
00172
00173
00174
00175 aP->Space = *xP;
00176 iov[1].iov_base = (char *)Space; n = strlen(Space);
00177 iov[1].iov_len = n;
00178
00179 return !XrdCnsSsi::Write(iFD, iov, 3, sizeof(Hdr)+n+1);
00180 }
00181
00182
00183
00184
00185
00186 int XrdCnsSsi::List(const char *Host, const char *Path)
00187 {
00188 XrdOucStream myIF;
00189 XrdCnsXref Mount("/",0), Space("public",0);
00190 XrdCnsLogRec::Arg *aP = 0;
00191 XrdOucNSWalk::NSEnt *nsP, *nsL, *nsI = 0;
00192 struct stat Stat;
00193 char pfxBuff[512], *pfxP = pfxBuff, *omP, *osP, *oSP;
00194 char hBuff[256], oBuff[MAXPATHLEN+1], *ofP = oBuff;
00195 char *tP, *lP;
00196 int pendLog, iFD;
00197 int dName = Config.Lopt & XrdCnsSsiCfg::Lname;
00198 int dMount= Config.Lopt & XrdCnsSsiCfg::Lmount;
00199
00200
00201
00202 nsL = XrdCnsLog::List(Path, &nsI, 1);
00203 pendLog = (nsL != 0);
00204 if (nsI) delete nsI;
00205 while((nsP = nsL)) {nsL = nsL->Next; delete nsP;}
00206
00207
00208
00209 if (!nsI) {Say.M("No inventory found for ", Host); return 4;}
00210
00211
00212
00213 strcpy(oBuff, Path); strcat(oBuff,"/"); strcat(oBuff, XrdCnsLog::invFNz);
00214 if ((iFD = open(oBuff, O_RDONLY)) < 0)
00215 {Say.M("Unable to process ",oBuff,"; ",
00216 XrdOucUtils::eText(errno, pfxBuff, sizeof(pfxBuff)));
00217 return 1;
00218 }
00219 myIF.Attach(iFD, 4096);
00220
00221
00222
00223 if (Config.Lopt & XrdCnsSsiCfg::Lhost)
00224 {strcpy(pfxP, Host); pfxP += strlen(pfxP); *pfxP++ = ' ';}
00225
00226 if (Config.Lopt & XrdCnsSsiCfg::Lmode)
00227 {omP = pfxP; pfxP += sizeof(aP->Mode); *pfxP++ = ' ';
00228 } else omP = 0;
00229
00230 oSP = osP = 0;
00231 if (Config.Lopt & XrdCnsSsiCfg::Lsize)
00232 {if (Config.Lopt & XrdCnsSsiCfg::Lfmts) oSP = pfxP;
00233 else osP = pfxP;
00234 pfxP += sizeof(aP->SorT); *pfxP++ = ' ';
00235 }
00236 *pfxP = '\0';
00237
00238
00239
00240 if ((lP = myIF.GetLine()) && *lP)
00241 {aP = (struct XrdCnsLogRec::Arg *)lP;
00242 if (aP->Type != XrdCnsLogRec::lrTOD) fstat(iFD,&Stat);
00243 else {Stat.st_ctime = strtol(aP->SorT,0,10) + XrdCnsLogRec::tBase;
00244 if (*(aP->lfn) && *(aP->lfn) != ' ')
00245 {strcpy(hBuff, aP->lfn); Host = hBuff;}
00246 lP = myIF.GetLine();
00247 }
00248 } else fstat(iFD,&Stat);
00249 tP = ctime(&Stat.st_ctime); tP[strlen(tP)-1] = '\0';
00250
00251
00252
00253 cout <<Host <<(pendLog? " in":" ") <<"complete inventory as of " <<tP <<endl;
00254
00255
00256
00257 if (lP && *lP)
00258 do {aP = (struct XrdCnsLogRec::Arg *)lP;
00259 switch(aP->Type)
00260 {case XrdCnsLogRec::lrMount: Mount.Add(aP->lfn, aP->Mount);
00261 continue;
00262 case XrdCnsLogRec::lrSpace: Space.Add(aP->lfn, aP->Space);
00263 continue;
00264 case XrdCnsLogRec::lrInvD: strcpy(oBuff, aP->lfn);
00265 ofP = oBuff + strlen(oBuff);
00266 *ofP++ = '/';
00267 continue;
00268 default: break;
00269 }
00270 if (omP) memcpy(omP, aP->Mode, sizeof(aP->Mode));
00271 if (oSP) FSize( oSP, aP->SorT, sizeof(aP->SorT));
00272 if (osP) memcpy(osP, aP->SorT, sizeof(aP->SorT));
00273 if (*pfxBuff) cout <<pfxBuff;
00274
00275 if (dName) cout <<Space.Key(aP->Space) <<' ';
00276 strcpy(ofP, aP->lfn);
00277 if (dMount) cout <<oBuff <<" -> " <<Mount.Key(aP->Mount) <<endl;
00278 else cout <<oBuff <<endl;
00279
00280 } while((lP = myIF.GetLine()) && *lP);
00281
00282
00283
00284 return 0;
00285 }
00286
00287
00288
00289
00290
00291 int XrdCnsSsi::Updt(const char *Host, const char *Path)
00292 {
00293 static const int AMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00294 class nsHelper
00295 {public:
00296 void Set(XrdOucNSWalk::NSEnt *nsP) {nsBase = nsP;}
00297 nsHelper() : nsBase(0) {}
00298 ~nsHelper() {XrdOucNSWalk::NSEnt *nsP;
00299 while((nsP = nsBase))
00300 {nsBase = nsP->Next; delete nsP;}
00301 }
00302 private:
00303 XrdOucNSWalk::NSEnt *nsBase;
00304 };
00305
00306 XrdOucStream myIF;
00307 XrdCnsXref Mount("/",0), Space("public",0);
00308 XrdOucSxeq myUP(".cns_ssi_updt.", Host);
00309 XrdOucHash<XrdCnsSsiDRec> myInv;
00310 XrdCnsSsiDRec *curDir = 0;
00311 XrdCnsSsiFRec *curFile;
00312 XrdCnsLogRec::Arg *aP = 0;
00313 XrdOucNSWalk::NSEnt *nsP, *nsL, *nsI = 0;
00314 nsHelper theNS;
00315 struct stat Stat;
00316 char cSave, iBuff[MAXPATHLEN+1], oBuff[MAXPATHLEN+1], *lP;
00317 int iFD, rc, TOD = 0;
00318
00319
00320
00321 if (!myUP.Serialize(XrdOucSxeq::noWait|XrdOucSxeq::Unlink))
00322 {rc = myUP.lastError();
00323 if (rc == EAGAIN)
00324 Say.M(Host, " inventory is already being updated.");
00325 else Say.M("Unable to update ", Host, " inventory; ",
00326 XrdOucUtils::eText(rc, oBuff, sizeof(oBuff)));
00327 return 8;
00328 }
00329
00330
00331
00332 nsL = XrdCnsLog::List(Path, &nsI, 1);
00333
00334
00335
00336 if (!nsI) {Say.M("No inventory found for ", Host);
00337 theNS.Set(nsL);
00338 return 0;
00339 }
00340
00341
00342
00343 if (!nsL) {Say.V(Host," inventory is up to date.");
00344 delete nsI;
00345 return 0;
00346 }
00347
00348
00349
00350 nsI->Next = nsL;
00351 theNS.Set(nsI);
00352 hInv = &myInv;
00353 mountP = &Mount;
00354 spaceP = &Space;
00355 nErrs = nDirs = nFiles = 0;
00356
00357
00358
00359 strcpy(iBuff, Path); strcat(iBuff,"/"); strcat(iBuff, XrdCnsLog::invFNz);
00360 if ((iFD = open(iBuff, O_RDONLY)) < 0)
00361 {Say.M("Unable to process ",iBuff,"; ",
00362 XrdOucUtils::eText(errno, oBuff, sizeof(oBuff)));
00363 return 1;
00364 }
00365 myIF.Attach(iFD, 4096);
00366
00367
00368
00369 if ((lP = myIF.GetLine()) && *lP)
00370 {aP = (struct XrdCnsLogRec::Arg *)lP;
00371 if (aP->Type == XrdCnsLogRec::lrTOD) lP = myIF.GetLine();
00372 }
00373
00374
00375
00376 if (lP && *lP)
00377 do {aP = (struct XrdCnsLogRec::Arg *)lP;
00378 switch(aP->Type)
00379 {case XrdCnsLogRec::lrMount: Mount.Add(aP->lfn, aP->Mount); break;
00380 case XrdCnsLogRec::lrSpace: Space.Add(aP->lfn, aP->Space); break;
00381 case XrdCnsLogRec::lrInvD: curDir = AddDir(aP->lfn, lP); break;
00382 default: if (curDir)
00383 {curFile = new XrdCnsSsiFRec(lP);
00384 curDir->Files->Rep(aP->lfn, curFile);
00385 } else Say.M("Ignoring file '", aP->lfn,
00386 "'; missing directory in inventory.");
00387 break;
00388 }
00389 } while((lP = myIF.GetLine()) && *lP);
00390
00391
00392
00393 fstat(iFD, &Stat);
00394 myIF.Close();
00395
00396
00397
00398 nsP = nsL;
00399 while(nsP)
00400 {if (nsP->Stat.st_ctime <= Stat.st_ctime)
00401 Say.V("Skipping ",nsP->File,"; too old.");
00402 else if (!(TOD = ApplyLog(nsP->Path))) return 8;
00403 nsP = nsP->Next;
00404 }
00405
00406
00407
00408 strcpy(oBuff, iBuff); lP = rindex(oBuff, '/')+1;
00409 cSave = *lP; *lP = 'i';
00410 if ((iFD = open(oBuff, O_CREAT|O_TRUNC|O_WRONLY, AMode)) < 0)
00411 {Say.M("Unable to create ", oBuff, "; ",
00412 XrdOucUtils::eText(errno, iBuff, sizeof(iBuff)));
00413 return 8;
00414 }
00415
00416
00417
00418 if (!Write(iFD, TOD, Host)) return 8;
00419
00420
00421
00422 Mount.Apply(XrdCnsSsiApplyM, (void *)&iFD);
00423 Space.Apply(XrdCnsSsiApplyS, (void *)&iFD);
00424
00425
00426
00427 if (myInv.Apply(XrdCnsSsiApplyD, (void *)&iFD)) {close(iFD); return 8;}
00428
00429
00430
00431 close(iFD);
00432 if (rename(oBuff, iBuff))
00433 {Say.M("Unable to rename ",oBuff," to the inventory; ",
00434 XrdOucUtils::eText(errno, iBuff, sizeof(iBuff)));
00435 return 8;
00436 }
00437
00438
00439
00440 while(nsL) {unlink(nsL->Path); nsL = nsL->Next;}
00441
00442
00443
00444 sprintf(oBuff, "%d director%s and %d file%s updated with %d error%s.",
00445 nDirs, (nDirs != 1 ? "ies" : "y"), nFiles, (nFiles != 1 ? "s" : ""),
00446 nErrs, (nErrs != 1 ? "s" : ""));
00447 Say.M(Host, " inventory with ", oBuff);
00448 return 0;
00449 }
00450
00451
00452
00453
00454
00455 int XrdCnsSsi::ApplyLog(const char *Path)
00456 {
00457 XrdOucStream myLog;
00458 XrdCnsLogRec::Arg *aP = 0;
00459 char eBuff[64], *lP;
00460 int logFD, TOD = 0, oldErrs = nErrs;
00461
00462
00463
00464 if ((logFD = open(Path, O_RDONLY)) < 0)
00465 {Say.M("Unable to process ",Path,"; ",
00466 XrdOucUtils::eText(errno, eBuff, sizeof(eBuff)));
00467 return 0;
00468 }
00469 myLog.Attach(logFD, 4096);
00470 Say.V("Processing log file ", Path);
00471
00472
00473
00474 while((lP = myLog.GetLine()) && *lP)
00475 {aP = (struct XrdCnsLogRec::Arg *)lP;
00476 if (*(aP->lfn) == '/') ApplyLogRec(lP);
00477 else if (aP->Type == XrdCnsLogRec::lrEOL
00478 || aP->Type == XrdCnsLogRec::lrTOD) TOD = atoi(aP->SorT);
00479 else {Say.V("Invalid log record: ", lP); nErrs++;}
00480 }
00481
00482
00483
00484 if (oldErrs != nErrs) Say.M("Errors encountered processing log ", Path);
00485
00486
00487
00488 if (!TOD)
00489 {struct stat Stat;
00490 fstat(logFD, &Stat);
00491 TOD = Stat.st_ctime - XrdCnsLogRec::tBase;
00492 }
00493
00494
00495
00496 return TOD;
00497 }
00498
00499
00500
00501
00502
00503 void XrdCnsSsi::ApplyLogRec(char *lP)
00504 {
00505 XrdCnsLogRec::Arg *aP = (XrdCnsLogRec::Arg *)lP;
00506 XrdCnsSsiDRec *theDir;
00507 char Type = aP->Type, *lfn = aP->lfn, *fnP = 0;
00508
00509
00510
00511 if (aP->Type != XrdCnsLogRec::lrMkdir
00512 && aP->Type != XrdCnsLogRec::lrRmdir
00513 && aP->Type != XrdCnsLogRec::lrCreate
00514 && aP->Type != XrdCnsLogRec::lrMv)
00515 {if (!(fnP = rindex(aP->lfn+1, '/')) || !(*(fnP+1))) Type = 0;
00516 else *fnP++ = '\0';
00517 }
00518
00519
00520
00521 switch (Type)
00522 {case XrdCnsLogRec::lrClosew: AddSize(lfn, fnP, lP); break;
00523 case XrdCnsLogRec::lrCreate: AddFile(lfn, lP); break;
00524 case XrdCnsLogRec::lrMkdir: AddDir (lfn, lP); break;
00525 case XrdCnsLogRec::lrRm: if ((theDir = hInv->Find(lfn)))
00526 theDir->Files->Del(fnP);
00527 break;
00528 case XrdCnsLogRec::lrRmdir: hInv->Del(lfn); break;
00529 case XrdCnsLogRec::lrMv: if (AddDel(lfn, lP)) break;
00530 default: if (fnP) *(fnP -1) = '/';
00531 Say.V("Invalid log record ", lP);
00532 nErrs++;
00533 }
00534 }
00535
00536
00537
00538
00539
00540 XrdCnsSsiDRec *XrdCnsSsi::AddDir(char *dP, char *lP)
00541 {
00542 XrdCnsSsiDRec *theDir;
00543
00544
00545
00546 if (!(theDir = hInv->Find(dP)))
00547 {theDir = new XrdCnsSsiDRec(lP);
00548 hInv->Add(dP, theDir);
00549 }
00550 return theDir;
00551 }
00552
00553
00554
00555
00556
00557 int XrdCnsSsi::AddDel(char *pPo, char *lP)
00558 {
00559 XrdCnsSsiDRec *newDir, *oldDir = hInv->Find(pPo);
00560 XrdCnsSsiFRec *oldFile, *newFile;
00561 char *diP = 0, *fnPo = 0, *fnPn = 0, *pPn = 0;
00562
00563
00564
00565 if (!(pPn = index(pPo, ' '))) return 0;
00566 *pPn++ = '\0';
00567
00568
00569
00570 if (oldDir)
00571 {newDir = AddDir(pPn, oldDir->Info);
00572 delete newDir->Files;
00573 newDir->Files = oldDir->Files;
00574 oldDir->Files = 0;
00575 hInv->Del(pPo);
00576 return 1;
00577 }
00578
00579
00580
00581 if (!(fnPo = rindex(pPo, '/')) || !(*(fnPo+1))
00582 || !(fnPn = rindex(pPn, '/')) || !(*(fnPn+1))) {*(pPn-1) = ' '; return 0;}
00583 *fnPo++ = '\0'; *fnPn++ = '\0';
00584
00585
00586
00587 if ((oldDir = hInv->Find(pPo)) && (oldFile = oldDir->Files->Find(fnPo)))
00588 {newFile = new XrdCnsSsiFRec(oldFile->Info);
00589 diP = oldDir->Info;
00590 oldDir->Files->Del(fnPo);
00591 } else newFile = new XrdCnsSsiFRec(0);
00592
00593
00594
00595 newDir = AddDir(pPn, diP);
00596 newDir->Files->Add(fnPn, newFile);
00597
00598
00599
00600 return 1;
00601 }
00602
00603
00604
00605
00606
00607 XrdCnsSsiFRec *XrdCnsSsi::AddFile(char *lfn, char *lP)
00608 {
00609 XrdCnsLogRec::Arg *aP = (XrdCnsLogRec::Arg *)lP;
00610 XrdCnsSsiDRec *theDir;
00611 XrdCnsSsiFRec *theFile;
00612 char *fP, *mP, *sP;
00613
00614
00615
00616 if ((sP = index(lfn, ' '))) *sP++ = '\0';
00617 if (!(fP = rindex(lfn+1, '/')) || !(*(fP+1)))
00618 {if (sP) *(sP-1) = ' ';
00619 Say.V("Invalid log record ", lP); nErrs++;
00620 return 0;
00621 }
00622 *fP++ = '\0';
00623 if (sP)
00624 {if (!(mP = index(sP, ' '))) aP->Mount = mountP->Default();
00625 else {*mP++ = '\0'; aP->Mount = mountP->Add(mP);}
00626 if (*sP) aP->Space = spaceP->Add(sP);
00627 else aP->Space = spaceP->Default();
00628 } else { aP->Mount = mountP->Default();
00629 aP->Space = spaceP->Default();
00630 }
00631
00632
00633
00634
00635 theDir = AddDir(lfn, 0);
00636 if ((theFile = theDir->Files->Find(fP))) theFile->Updt(lP);
00637 else {theFile = new XrdCnsSsiFRec(lP);
00638 theDir->Files->Add(fP, theFile);
00639 }
00640 return theFile;
00641 }
00642
00643
00644
00645 XrdCnsSsiFRec *XrdCnsSsi::AddFile(char *dP, char *fP, char *lP)
00646 {
00647 XrdCnsSsiDRec *theDir = AddDir(dP, 0);
00648 XrdCnsSsiFRec *theFile;
00649
00650
00651
00652 if ((theFile = theDir->Files->Find(fP))) theFile->Updt(lP);
00653 else {theFile = new XrdCnsSsiFRec(lP);
00654 theDir->Files->Add(fP, theFile);
00655 }
00656 return theFile;
00657 }
00658
00659
00660
00661
00662
00663 void XrdCnsSsi::AddSize(char *dP, char *fP, char *lP)
00664 {
00665 XrdCnsLogRec::Arg *nP = (XrdCnsLogRec::Arg *)lP;
00666 XrdCnsSsiDRec *theDir = hInv->Find(dP);
00667 XrdCnsSsiFRec *theFile;
00668
00669
00670
00671 if (!theDir || !(theFile = theDir->Files->Find(fP)))
00672 theFile = AddFile(dP, fP, 0);
00673 XrdCnsLogRec::Arg *aP = (XrdCnsLogRec::Arg *)(theFile->Info);
00674 strncpy(aP->SorT, nP->SorT, sizeof(aP->SorT));
00675 }
00676
00677
00678
00679
00680
00681 void XrdCnsSsi::FSize(char *oP, char *iP, int bsz)
00682 {
00683 static const long long Kval = 1024LL;
00684 static const long long Mval = 1024LL*1024LL;
00685 static const long long Gval = 1024LL*1024LL*1024LL;
00686 static const long long Tval = 1024LL*1024LL*1024LL*1024LL;
00687 long long val;
00688 char buff[32], sName = ' ';
00689 int n, resid;
00690
00691
00692
00693 val = strtoll(iP, 0, 10);
00694
00695
00696
00697 if (val < 1024) {memcpy(oP, iP, bsz); return;}
00698 if (val < Mval) {val = val*10/Kval; sName = 'K';}
00699 else if (val < Gval) {val = val*10/Mval; sName = 'M';}
00700 else if (val < Tval) {val = val*10/Gval; sName = 'G';}
00701 else {val = val*10/Tval; sName = 'T';}
00702 resid = val%10LL; val = val/10LL;
00703
00704
00705
00706 n = sprintf(buff,"%lld.%d%c", val, resid, sName);
00707 memset(oP, ' ', bsz);
00708 strncpy(oP+(bsz-n), buff, n);
00709 }
00710
00711
00712
00713
00714
00715 int XrdCnsSsi::Write(int xFD, char *bP, int bL)
00716 {
00717 char eBuff[64];
00718 int rc;
00719
00720 do {do {rc = write(xFD, bP, bL);} while (rc < 0 && errno == EINTR);
00721 if (rc < 0) {Say.M("Unable to update inventory; ",
00722 XrdOucUtils::eText(errno, eBuff, sizeof(eBuff)));
00723 return 0;
00724 }
00725 bP += rc; bL -= rc;
00726 } while(bL > 0);
00727
00728 return 1;
00729 }
00730
00731
00732
00733 int XrdCnsSsi::Write(int xFD, struct iovec *iov, int n, int Bytes)
00734 {
00735 char eBuff[64], *Buff;
00736 int rc, i, Blen;
00737
00738 do {rc = writev(xFD, iov, n);} while(rc < 0 && errno == EINTR);
00739 if (rc < 0) {Say.M("Unable to update inventory; ",
00740 XrdOucUtils::eText(errno, eBuff, sizeof(eBuff)));
00741 return 0;
00742 }
00743
00744 if (rc == Bytes) return 1;
00745
00746 for (i = 0; i < n; i++)
00747 {if (Bytes >= (int)iov[i].iov_len) Bytes -= iov[i].iov_len;
00748 else {Buff = Bytes + (char *)iov[i].iov_base;
00749 Blen = iov[i].iov_len - Bytes;
00750 if (!Write(xFD, Buff, Blen)) return 0;
00751 Bytes = 0;
00752 }
00753 }
00754
00755 return 1;
00756 }
00757
00758
00759
00760 int XrdCnsSsi::Write(int iFD, int TOD, const char *Host)
00761 {
00762 XrdCnsLogRec::Arg tRec;
00763 char buff[32];
00764 int n;
00765
00766 memset(&tRec, ' ', XrdCnsLogRec::FixDLen);
00767 tRec.Type = XrdCnsLogRec::lrTOD;
00768 memset(tRec.Mode, '0', sizeof(tRec.Mode));
00769 n = sprintf(buff, "%d", TOD);
00770 memcpy(tRec.SorT+sizeof(tRec.SorT)-n, buff, n);
00771 strcpy(tRec.lfn, Host);
00772 n = strlen(tRec.lfn);
00773 tRec.lfn[n] = '\n';
00774 return Write(iFD, (char *)&tRec, XrdCnsLogRec::FixDLen+n+1);
00775 }