XrdFrmFiles.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                        X r d F r m F i l e s . 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: XrdFrmFiles.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 #include <errno.h>
00014 #include <string.h>
00015 #include <strings.h>
00016 #include <unistd.h>
00017 #include <fcntl.h>
00018 #include <sys/param.h>
00019 #include <sys/stat.h>
00020 #include <sys/types.h>
00021 
00022 #include "XrdFrm/XrdFrmConfig.hh"
00023 #include "XrdFrm/XrdFrmFiles.hh"
00024 #include "XrdFrm/XrdFrmTrace.hh"
00025 #include "XrdOuc/XrdOucTList.hh"
00026 #include "XrdSys/XrdSysPlatform.hh"
00027 
00028 const char *XrdFrmFilesCVSID = "$Id: XrdFrmFiles.cc 35287 2010-09-14 21:19:35Z ganis $";
00029 
00030 using namespace XrdFrm;
00031 
00032 /******************************************************************************/
00033 /*                   C l a s s   X r d F r m F i l e s e t                    */
00034 /******************************************************************************/
00035 /******************************************************************************/
00036 /*                           C o n s t r u c t o r                            */
00037 /******************************************************************************/
00038   
00039 XrdFrmFileset::XrdFrmFileset(XrdFrmFileset *sP, XrdOucTList *diP)
00040               : Next(sP), dInfo(diP), dlkFD(-1), flkFD(-1)
00041 {  memset(File, 0, sizeof(File));
00042    if (diP) diP->ival[dRef]++;
00043 }
00044 
00045 /******************************************************************************/
00046 /*                            D e s t r u c t o r                             */
00047 /******************************************************************************/
00048   
00049 XrdFrmFileset::~XrdFrmFileset()
00050 {
00051    int i;
00052 
00053 // Unlock any locked files
00054 //
00055    UnLock();
00056 
00057 // Delete all the table entries
00058 //
00059    for (i = 0; i < XrdOssPath::sfxNum; i++) if(File[i]) delete File[i];
00060 
00061 // If there is a shared directory buffer, decrease reference count, delete if 0
00062 //
00063    if (dInfo && ((dInfo->ival[dRef] -= 1) <= 0)) delete dInfo;
00064 }
00065 
00066 /******************************************************************************/
00067 /*                               d i r P a t h                                */
00068 /******************************************************************************/
00069   
00070 int XrdFrmFileset::dirPath(char *dBuff, int dBlen)
00071 {
00072    char *dP = 0;
00073    int   dN = 0, i;
00074 
00075 // If we have a shared directory pointer, use that as directory information
00076 // Otherwise, get it from one of the files in the fileset.
00077 //
00078    if (dInfo) {dP = dInfo->text; dN = dInfo->ival[dLen];}
00079       else {for (i = 0; i < XrdOssPath::sfxNum; i++)
00080                 if (File[i])
00081                    {dP = File[i]->Path;
00082                     dN = File[i]->File - File[i]->Path;
00083                     break;
00084                    }
00085            }
00086 
00087 // Copy out the directory path
00088 //
00089    if (dBlen > dN && dP) strncpy(dBuff, dP, dN);
00090       else dN = 0;
00091    *(dBuff+dN) = '\0';
00092    return dN;
00093 }
00094 
00095 /******************************************************************************/
00096 /*                               R e f r e s h                                */
00097 /******************************************************************************/
00098   
00099 int XrdFrmFileset::Refresh(int isMig, int doLock)
00100 {
00101    XrdOucNSWalk::NSEnt *bP = baseFile(), *lP = lockFile();
00102    char pBuff[MAXPATHLEN+1], *fnP, *pnP = pBuff;
00103    int n;
00104 
00105 // Get the directory path for this entry
00106 //
00107    if (!(n = dirPath(pBuff, sizeof(pBuff)-1))) return 0;
00108    fnP = pBuff+n;
00109 
00110 // If we need to lock the entry, do so. We also check if file is in use
00111 //
00112    if (doLock && bP)
00113       {strcpy(fnP, baseFile()->File);
00114        if (chkLock(pBuff)) return 0;
00115        if (lP && dlkFD < 0)
00116           {strcpy(fnP, Config.lockFN);
00117            if ((dlkFD = getLock(pBuff)) < 0) return 0;
00118            strcpy(fnP, lockFile()->File);
00119            if ((flkFD = getLock(pBuff,0,1)) < 0)
00120               {close(dlkFD); dlkFD = -1; return 0;}
00121           }
00122       }
00123 
00124 // Do a new stat call on each relevant file (pin file excluded for isMig)
00125 //
00126    if (bP)
00127       {if (bP->Link) pnP = bP->Link;
00128          else strcpy(fnP, bP->File);
00129        if (stat(pnP, &(bP->Stat)))
00130           {Say.Emsg("Refresh", errno, "stat", pnP); UnLock(); return 0;}
00131       }
00132 
00133    if (lP)
00134       {strcpy(fnP, lP->File);
00135        if (stat(pBuff, &(lP->Stat)))
00136           {Say.Emsg("Refresh", errno, "stat", pBuff); UnLock(); return 0;}
00137       }
00138 
00139    if (!isMig && (bP = pinFile()))
00140       {strcpy(fnP, bP->File);
00141        if (stat(pBuff, &(bP->Stat)) && errno == ENOENT)
00142           {delete bP; File[XrdOssPath::isPin] = 0;}
00143       }
00144 
00145 // All done
00146 //
00147    return 1;
00148 }
00149 
00150 /******************************************************************************/
00151 /*                                U n L o c k                                 */
00152 /******************************************************************************/
00153   
00154 void XrdFrmFileset::UnLock()
00155 {
00156    if (flkFD >= 0) {close(flkFD); flkFD = -1;}
00157    if (dlkFD >= 0) {close(dlkFD); dlkFD = -1;}
00158 }
00159 
00160 /******************************************************************************/
00161 /*                       P r i v a t e   M e t h o d s                        */
00162 /******************************************************************************/
00163 /******************************************************************************/
00164 /*                               c h k L o c k                                */
00165 /******************************************************************************/
00166 
00167 // Returns 0 if no lock exists o/w returns 1 or -1;
00168   
00169 int XrdFrmFileset::chkLock(const char *Path)
00170 {
00171    FLOCK_t lock_args;
00172    int rc, lokFD;
00173 
00174 // Open the file appropriately
00175 //
00176    if ((lokFD = open(Path, O_RDONLY)) < 0)
00177       {Say.Emsg("chkLock", errno, "open", Path); return -1;}
00178 
00179 // Initialize the lock arguments
00180 //
00181    bzero(&lock_args, sizeof(lock_args));
00182    lock_args.l_type = F_WRLCK;
00183 
00184 // Now check if the lock can be obtained
00185 //
00186    do {rc = fcntl(lokFD, F_GETLK, &lock_args);} while(rc < 0 && errno == EINTR);
00187 
00188 // Determine the result
00189 //
00190    if (rc) Say.Emsg("chkLock", errno, "lock", Path);
00191       else rc = (lock_args.l_type == F_UNLCK ? 0 : 1);
00192 
00193 // All done
00194 //
00195    close(lokFD);
00196    return rc;
00197 }
00198 
00199 /******************************************************************************/
00200 /*                               g e t L o c k                                */
00201 /******************************************************************************/
00202   
00203 int XrdFrmFileset::getLock(char *Path, int Shared, int noWait)
00204 {
00205    static const int AMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
00206    FLOCK_t lock_args;
00207    int oFlags = (Shared ? O_RDONLY : O_RDWR|O_CREAT);
00208    int rc, lokFD, Act;
00209 
00210 // Open the file appropriately
00211 //
00212    if ((lokFD = open(Path, oFlags, AMode)) < 0)
00213       {Say.Emsg("getLock", errno, "open", Path); return -1;}
00214 
00215 // Initialize the lock arguments
00216 //
00217    bzero(&lock_args, sizeof(lock_args));
00218    lock_args.l_type = (Shared ? F_RDLCK : F_WRLCK);
00219    Act = (noWait ? F_SETLK : F_SETLKW);
00220 
00221 // Now obtain the lock
00222 //
00223    do {rc = fcntl(lokFD, Act, &lock_args);} while(rc < 0 && errno == EINTR);
00224 
00225 // Determine the result
00226 //
00227    if (rc)
00228       {if (errno != EAGAIN) Say.Emsg("getLock", errno, "lock", Path);
00229        close(lokFD); return -1;
00230       }
00231 
00232 // All done
00233 //
00234    return lokFD;
00235 }
00236 
00237 /******************************************************************************/
00238 /*                                  M k f n                                   */
00239 /******************************************************************************/
00240   
00241 const char *XrdFrmFileset::Mkfn(XrdOucNSWalk::NSEnt *fP)
00242 {
00243 
00244 // If we have no file for this, return the null string
00245 //
00246    if (!fP) return "";
00247 
00248 // If we have no shared directory pointer, return the full path
00249 //
00250    if (!dInfo) return fP->Path;
00251 
00252 // Construct the name in a non-renterant way (this is documented)
00253 //
00254    strcpy(dInfo->text+dInfo->ival[dLen], fP->File);
00255    return dInfo->text;
00256 }
00257   
00258 /******************************************************************************/
00259 /*                     C l a s s   X r d F r m F i l e s                      */
00260 /******************************************************************************/
00261 /******************************************************************************/
00262 /*                           C o n s t r u c t o r                            */
00263 /******************************************************************************/
00264   
00265 XrdFrmFiles::XrdFrmFiles(const char *dname, int opts,
00266                         XrdOucTList *XList, XrdOucNSWalk::CallBack *cbP)
00267             : nsObj(&Say, dname, Config.lockFN,
00268                     XrdOucNSWalk::retFile | XrdOucNSWalk::retLink
00269                    |XrdOucNSWalk::retStat | XrdOucNSWalk::skpErrs
00270                    |XrdOucNSWalk::retIILO
00271                    | (opts & CompressD  ?   XrdOucNSWalk::noPath  : 0)
00272                    | (opts & Recursive  ?   XrdOucNSWalk::Recurse : 0), XList),
00273               fsList(0), manMem(opts & NoAutoDel ? Hash_keep : Hash_default),
00274               shareD(opts & CompressD)
00275 {
00276 
00277 // Set Call Back method
00278 //
00279    nsObj.setCallBack(cbP);
00280 }
00281 
00282 /******************************************************************************/
00283 /*                                   G e t                                    */
00284 /******************************************************************************/
00285   
00286 XrdFrmFileset *XrdFrmFiles::Get(int &rc, int noBase)
00287 {
00288    XrdOucNSWalk::NSEnt *nP;
00289    XrdFrmFileset *fsetP;
00290    const char *dPath;
00291 
00292 // Check if we have something to return
00293 //
00294 do{while ((fsetP = fsList))
00295          {fsList = fsetP->Next; fsetP->Next = 0;
00296           if (fsetP->File[XrdOssPath::isBase] || noBase) {rc = 0; return fsetP;}
00297              else if (manMem) delete fsetP;
00298          }
00299 
00300 // Start with next directory (we return when no directories left).
00301 //
00302    do {if (!(nP = nsObj.Index(rc, &dPath))) return 0;
00303        fsTab.Purge(); fsList = 0;
00304       } while(!Process(nP, dPath));
00305 
00306   } while(1);
00307 
00308 // To keep the compiler happy
00309 //
00310    return 0;
00311 }
00312 
00313 /******************************************************************************/
00314 /*                       P r i v a t e   M e t h o d s                        */
00315 /******************************************************************************/
00316 /******************************************************************************/
00317 /*                               P r o c e s s                                */
00318 /******************************************************************************/
00319   
00320 int XrdFrmFiles::Process(XrdOucNSWalk::NSEnt *nP, const char *dPath)
00321 {
00322    XrdOucNSWalk::NSEnt *fP;
00323    XrdFrmFileset       *sP;
00324    XrdOucTList         *dP = 0;
00325    char *dotP;
00326    int fType;
00327 
00328 // If compressed directories wanted, then setup a shared directory buffer
00329 // Warning! We use a hard-coded value for maximum filename length instead of
00330 //          constantly calling pathconf().
00331 //
00332    if (shareD)
00333       {int n = strlen(dPath);
00334        char *dBuff = (char *)malloc(n+264);
00335        strcpy(dBuff, dPath);
00336        dP = new XrdOucTList;
00337        dP->text = dBuff;
00338        dP->ival[XrdFrmFileset::dLen] = n;
00339        dP->ival[XrdFrmFileset::dRef] = 0;
00340       }
00341 
00342 // Process the file list
00343 //
00344    while((fP = nP))
00345         {nP = fP->Next; fP->Next = 0;
00346          if (!strcmp(fP->File, Config.lockFN)) {delete fP; continue;}
00347          if ((fType = (int)XrdOssPath::pathType(fP->File))
00348          && (dotP = rindex(fP->File, '.'))) *dotP = '\0';
00349             else dotP = 0;
00350          if (!(sP = fsTab.Find(fP->File)))
00351             {sP = fsList = new XrdFrmFileset(fsList, dP);
00352              fsTab.Add(fP->File, sP, 0, manMem);
00353             }
00354          if (dotP) *dotP = '.';
00355          sP->File[fType] = fP;
00356         }
00357 
00358 // Indicate whether we have anything here
00359 //
00360    if (fsList) return 1;
00361    if (dP) delete dP;
00362    return 0;
00363 }

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