XrdCnsSsi.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d C n s S s i . c c                           */
00004 /*                                                                            */
00005 /* (c) 2009 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: XrdCnsSsi.cc 34000 2010-06-21 06:49:56Z ganis $
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 /*                         L o c a l   C l a s s e s                          */
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 /*           G l o b a l   C o n f i g u r a t i o n   O b j e c t            */
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 /*                   E x t e r n a l   I n t e r f a c e s                    */
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 // Return if there are no files in this directory
00115 //
00116    if (dP->Files->Num() <= 0) return 0;
00117 
00118 // Write out a directory record. Terminate processing upon error
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 // Now index through all of the file in this directory
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 // Initialize the header (needs to be done once)
00141 //
00142    if (doInit)
00143       {memset(Hdr, ' ', sizeof(Hdr));
00144        aP->Type = XrdCnsLogRec::lrMount;
00145        doInit = 0;
00146       }
00147 
00148 // Write out a directory record. Terminate processing upon error
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 // Initialize the header (needs to be done once
00166 //
00167    if (doInit)
00168       {memset(Hdr, ' ', sizeof(Hdr));
00169        aP->Type = XrdCnsLogRec::lrSpace;
00170        doInit = 0;
00171       }
00172 
00173 // Write out a directory record. Terminate processing upon error
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 /*                                  L i s t                                   */
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 // First step is to get the files in this directory
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 // If we have no inventory say so and return
00208 //
00209    if (!nsI) {Say.M("No inventory found for ", Host); return 4;}
00210 
00211 // Open the inventory file and attach it to a stream
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 // Preformat the output buffer
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 // The first line should be a time stamp. If it is not us the file's ctime
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  // Produce the header
00252  //
00253    cout <<Host <<(pendLog? " in":" ") <<"complete inventory as of " <<tP <<endl;
00254 
00255 // Produce the listing
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 // All done
00283 //
00284    return 0;
00285 }
00286 
00287 /******************************************************************************/
00288 /*                                  U p d t                                   */
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 // Make sure we are the only ones running here for this directory
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 // Now get the files in this directory
00331 //
00332    nsL = XrdCnsLog::List(Path, &nsI, 1);
00333 
00334 // If we have no inventory say so and return
00335 //
00336    if (!nsI) {Say.M("No inventory found for ", Host);
00337               theNS.Set(nsL);
00338               return 0;
00339              }
00340 
00341 // If no pending log files, no need to update the inventory
00342 //
00343    if (!nsL) {Say.V(Host," inventory is up to date.");
00344               delete nsI;
00345               return 0;
00346              }
00347 
00348 // Make sure that the full ns list is deleted
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 // Open the inventory file and attach it to a stream
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 // The first line should be a time stamp. If it is, throw it away.
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 // Populate the hash table with the inventory
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 // Done with the inventory
00392 //
00393    fstat(iFD, &Stat);
00394    myIF.Close();
00395 
00396 // Now apply each log file against the inventory
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 // Now we can open a shadow inventory file
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 // Create a TOD record based on the last TOD received
00417 //
00418    if (!Write(iFD, TOD, Host)) return 8;
00419 
00420 // Output the space names ans mount points
00421 //
00422    Mount.Apply(XrdCnsSsiApplyM, (void *)&iFD);
00423    Space.Apply(XrdCnsSsiApplyS, (void *)&iFD);
00424 
00425 // Now output the whole name space into the inventory file
00426 //
00427    if (myInv.Apply(XrdCnsSsiApplyD, (void *)&iFD)) {close(iFD); return 8;}
00428 
00429 // Close the file and rename it
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 // Now unlink all of the log files we processed
00439 //
00440    while(nsL) {unlink(nsL->Path); nsL = nsL->Next;}
00441 
00442 // Success. All resources will be deleted upon return
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 /*                              A p p l y L o g                               */
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 // Open the log file
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 // Update the hash table with the log file
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 // Check if we need to issue a warning
00483 //
00484    if (oldErrs != nErrs) Say.M("Errors encountered processing log ", Path);
00485 
00486 // Check if we should manufacture a TOD
00487 //
00488    if (!TOD)
00489       {struct stat Stat;
00490        fstat(logFD, &Stat);
00491        TOD = Stat.st_ctime - XrdCnsLogRec::tBase;
00492       }
00493 
00494 // All done, the file will be closed by the stream on exit
00495 //
00496    return TOD;
00497 }
00498 
00499 /******************************************************************************/
00500 /*                           A p p l y L o g R e c                            */
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 // Preprosess the record to establish dir/fn relationships
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 // Switch on record type
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 /* Private:                       A d d D i r                                 */
00538 /******************************************************************************/
00539   
00540 XrdCnsSsiDRec *XrdCnsSsi::AddDir(char *dP, char *lP)
00541 {
00542    XrdCnsSsiDRec *theDir;
00543 
00544 // Find the directory or create one
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 /* Private:                       A d d D e l                                 */
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 // Isolate the two lfn's
00564 //
00565    if (!(pPn = index(pPo, ' '))) return 0;
00566    *pPn++ = '\0';
00567 
00568 // First see if this is a directory rename
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 // Prepare for a file rename
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 // Now delete the old file
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 // Add the new file
00594 //
00595    newDir = AddDir(pPn, diP);
00596    newDir->Files->Add(fnPn, newFile);
00597 
00598 // All done
00599 //
00600    return 1;
00601 }
00602 
00603 /******************************************************************************/
00604 /* Private:                      A d d F i l e                                */
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 // Extract out the directory, file name, space name and mount point, if any
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 // Add the file if it does not exist
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 // Add the file if it does not exist
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 /* Private:                      A d d S i z e                                */
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 // Find directory
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 /* Private:                        F S i z e                                  */
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 // Convert the number
00692 //
00693    val = strtoll(iP, 0, 10);
00694 
00695 // Get correct scaling
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 // Format it
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 /*                                 W r i t e                                  */
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 }

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