XrdOssCache.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                        X r d O s s C a c h e . c c                         */
00004 /*                                                                            */
00005 /* (c) 2003 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-AC03-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010 
00011 //         $Id: XrdOssCache.cc 34000 2010-06-21 06:49:56Z ganis $
00012 
00013 const char *XrdOssCacheCVSID = "$Id: XrdOssCache.cc 34000 2010-06-21 06:49:56Z ganis $";
00014 
00015 #include <unistd.h>
00016 #include <errno.h>
00017 #include <fcntl.h>
00018 #include <stdio.h>
00019 #include <strings.h>
00020 #include <time.h>
00021 #include <sys/param.h>
00022 #include <sys/types.h>
00023 #include <sys/stat.h>
00024 
00025 #include "XrdOss/XrdOssCache.hh"
00026 #include "XrdOss/XrdOssOpaque.hh"
00027 #include "XrdOss/XrdOssPath.hh"
00028 #include "XrdOss/XrdOssSpace.hh"
00029 #include "XrdOss/XrdOssTrace.hh"
00030 #include "XrdSys/XrdSysHeaders.hh"
00031 #include "XrdSys/XrdSysPlatform.hh"
00032   
00033 /******************************************************************************/
00034 /*            G l o b a l s   a n d   S t a t i c   M e m b e r s             */
00035 /******************************************************************************/
00036 
00037 extern XrdSysError  OssEroute;
00038 
00039 extern XrdOucTrace  OssTrace;
00040 
00041 XrdOssCache_Group  *XrdOssCache_Group::fsgroups = 0;
00042 
00043 long long           XrdOssCache_Group::PubQuota = -1;
00044 
00045 XrdSysMutex         XrdOssCache::Mutex;
00046 long long           XrdOssCache::fsTotal = 0;
00047 long long           XrdOssCache::fsLarge = 0;
00048 long long           XrdOssCache::fsTotFr = 0;
00049 long long           XrdOssCache::fsFree  = 0;
00050 long long           XrdOssCache::fsSize  = 0;
00051 XrdOssCache_FS     *XrdOssCache::fsfirst = 0;
00052 XrdOssCache_FS     *XrdOssCache::fslast  = 0;
00053 XrdOssCache_FSData *XrdOssCache::fsdata  = 0;
00054 double              XrdOssCache::fuzAlloc= 0.0;
00055 long long           XrdOssCache::minAlloc= 0;
00056 int                 XrdOssCache::fsCount = 0;
00057 int                 XrdOssCache::ovhAlloc= 0;
00058 int                 XrdOssCache::Quotas  = 0;
00059 int                 XrdOssCache::Usage   = 0;
00060 
00061 /******************************************************************************/
00062 /*            X r d O s s C a c h e _ F S D a t a   M e t h o d s             */
00063 /******************************************************************************/
00064   
00065 XrdOssCache_FSData::XrdOssCache_FSData(const char *fsp, 
00066                                        STATFS_t   &fsbuff,
00067                                        dev_t       fsID)
00068 {
00069 
00070      path = strdup(fsp);
00071      size = static_cast<long long>(fsbuff.f_blocks)
00072           * static_cast<long long>(fsbuff.FS_BLKSZ);
00073      frsz = static_cast<long long>(fsbuff.f_bavail)
00074           * static_cast<long long>(fsbuff.FS_BLKSZ);
00075      XrdOssCache::fsTotal += size;
00076      XrdOssCache::fsTotFr += frsz;
00077      XrdOssCache::fsCount++;
00078      if (size > XrdOssCache::fsLarge) XrdOssCache::fsLarge= size;
00079      if (frsz > XrdOssCache::fsFree)  XrdOssCache::fsFree = frsz;
00080      fsid = fsID;
00081      updt = time(0);
00082      next = 0;
00083      stat = 0;
00084 }
00085   
00086 /******************************************************************************/
00087 /*            X r d O s s C a c h e _ F S   C o n s t r u c t o r             */
00088 /******************************************************************************/
00089 
00090 // Cache_FS objects are only created during configuration. No locks are needed.
00091   
00092 XrdOssCache_FS::XrdOssCache_FS(int &retc,
00093                                const char *fsGrp,
00094                                const char *fsPath,
00095                                FSOpts      fsOpts)
00096 {
00097    static const mode_t theMode = S_IRWXU | S_IRWXG;
00098    STATFS_t fsbuff;
00099    struct stat sfbuff;
00100    XrdOssCache_FSData *fdp;
00101    XrdOssCache_FS     *fsp;
00102 
00103 // Prefill in case of failure
00104 //
00105    path = group = 0;
00106 
00107 // Verify that this is not a duplicate
00108 //
00109    fsp = XrdOssCache::fsfirst;
00110    while(fsp && (strcmp(fsp->path,fsPath)||strcmp(fsp->fsgroup->group,fsGrp)))
00111         if ((fsp = fsp->next) == XrdOssCache::fsfirst) {fsp = 0; break;}
00112    if (fsp) {retc = EEXIST; return;}
00113 
00114 // Set the groupname and the path which is the supplied path/group name
00115 //
00116    if (!(fsOpts & isXA)) path = strdup(fsPath);
00117       else {path = XrdOssPath::genPath(fsPath, fsGrp, suffix);
00118             if (mkdir(path, theMode) && errno != EEXIST) {retc=errno; return;}
00119            }
00120    plen   = strlen(path);
00121    group  = strdup(fsGrp); 
00122    fsgroup= 0;
00123    opts   = fsOpts;
00124    retc   = ENOMEM;
00125 
00126 // Find the filesystem for this object
00127 //
00128    if (FS_Stat(fsPath, &fsbuff) || stat(fsPath, &sfbuff)) {retc=errno; return;}
00129 
00130 // Find the matching filesystem data
00131 //
00132    fdp = XrdOssCache::fsdata;
00133    while(fdp) {if (fdp->fsid == sfbuff.st_dev) break; fdp = fdp->next;}
00134 
00135 // If we didn't find the filesystem, then create one
00136 //
00137    if (!fdp)
00138       {if (!(fdp = new XrdOssCache_FSData(fsPath,fsbuff,sfbuff.st_dev))) return;
00139           else {fdp->next = XrdOssCache::fsdata; XrdOssCache::fsdata = fdp;}
00140       }
00141 
00142 // Complete the filesystem block (failure now is not an option)
00143 //
00144    fsdata = fdp;
00145    retc   = 0;
00146 
00147 // Link this filesystem into the filesystem chain
00148 //
00149    if (!XrdOssCache::fsfirst) {next = this;
00150                                XrdOssCache::fsfirst = this;
00151                                XrdOssCache::fslast  = this;
00152                               }
00153       else {next = XrdOssCache::fslast->next;
00154                    XrdOssCache::fslast->next = this;
00155                    XrdOssCache::fslast       = this;
00156            }
00157 
00158 // Check if this is the first group allocation
00159 //
00160    fsgroup = XrdOssCache_Group::fsgroups;
00161    while(fsgroup && strcmp(group, fsgroup->group)) fsgroup = fsgroup->next;
00162    if (!fsgroup && (fsgroup = new XrdOssCache_Group(group, this)))
00163       {fsgroup->next = XrdOssCache_Group::fsgroups; 
00164        XrdOssCache_Group::fsgroups=fsgroup;
00165       }
00166 }
00167 
00168 /******************************************************************************/
00169 /*                                   A d d                                    */
00170 /******************************************************************************/
00171 
00172 // Add is only called during configuration. No locks are needed. It merely
00173 // adds an unnamed file system partition. This allows us to track space.
00174   
00175 int XrdOssCache_FS::Add(const char *fsPath)
00176 {
00177    STATFS_t fsbuff;
00178    struct stat sfbuff;
00179    XrdOssCache_FSData *fdp;
00180 
00181 // Find the filesystem for this object
00182 //
00183    if (FS_Stat(fsPath, &fsbuff) || stat(fsPath, &sfbuff)) return -errno;
00184 
00185 // Find the matching filesystem data
00186 //
00187    fdp = XrdOssCache::fsdata;
00188    while(fdp) {if (fdp->fsid == sfbuff.st_dev) break; fdp = fdp->next;}
00189    if (fdp) return 0;
00190 
00191 // Create new filesystem data that will not be linked to any filesystem
00192 //
00193    if (!(fdp = new XrdOssCache_FSData(fsPath,fsbuff,sfbuff.st_dev)))
00194       return -ENOMEM;
00195    fdp->next = XrdOssCache::fsdata;
00196    XrdOssCache::fsdata = fdp;
00197    return 0;
00198 }
00199   
00200 /******************************************************************************/
00201 /*                             f r e e S p a c e                              */
00202 /******************************************************************************/
00203 
00204 long long XrdOssCache_FS::freeSpace(long long &Size, const char *path)
00205 {
00206    STATFS_t fsbuff;
00207    long long fSpace;
00208 
00209 // Free space for a specific path
00210 //
00211    if (path)
00212       {if (FS_Stat(path, &fsbuff)) return -1;
00213        Size = static_cast<long long>(fsbuff.f_blocks)
00214             * static_cast<long long>(fsbuff.FS_BLKSZ);
00215        return static_cast<long long>(fsbuff.f_bavail)
00216             * static_cast<long long>(fsbuff.FS_BLKSZ);
00217       }
00218 
00219 // Free space for the whole system
00220 //
00221    XrdOssCache::Mutex.Lock();
00222    fSpace = XrdOssCache::fsFree;
00223    Size   = XrdOssCache::fsSize;
00224    XrdOssCache::Mutex.UnLock();
00225    return fSpace;
00226 }
00227 
00228 /******************************************************************************/
00229 
00230 long long XrdOssCache_FS::freeSpace(XrdOssCache_Space &Space, const char *path)
00231 {
00232    STATFS_t fsbuff;
00233 
00234 // Free space for a specific path
00235 //
00236    if (!path || FS_Stat(path, &fsbuff)) return -1;
00237 
00238    Space.Total = static_cast<long long>(fsbuff.f_blocks)
00239                * static_cast<long long>(fsbuff.FS_BLKSZ);
00240    Space.Free  = static_cast<long long>(fsbuff.f_bavail)
00241                * static_cast<long long>(fsbuff.FS_BLKSZ);
00242    Space.Inodes= static_cast<long long>(fsbuff.f_files);
00243    Space.Inleft= static_cast<long long>(fsbuff.FS_FFREE);
00244 
00245    return Space.Free;
00246 }
00247 
00248 /******************************************************************************/
00249 /*                              g e t S p a c e                               */
00250 /******************************************************************************/
00251   
00252 int XrdOssCache_FS::getSpace(XrdOssCache_Space &Space, const char *sname)
00253 {
00254    XrdOssCache_Group  *fsg = XrdOssCache_Group::fsgroups;
00255 
00256 // Try to find the space group name
00257 //
00258    while(fsg && strcmp(sname, fsg->group)) fsg = fsg->next;
00259    if (!fsg) return 0;
00260 
00261 // Return the space
00262 //
00263    return getSpace(Space, fsg);
00264 }
00265 
00266 /******************************************************************************/
00267   
00268 int XrdOssCache_FS::getSpace(XrdOssCache_Space &Space, XrdOssCache_Group *fsg)
00269 {
00270    XrdOssCache_FS     *fsp;
00271    XrdOssCache_FSData *fsd;
00272    int pnum = 0;
00273 
00274 // Initialize some fields
00275 //
00276    Space.Total = 0;
00277    Space.Free  = 0;
00278 
00279 // Prepare to accumulate the stats
00280 //
00281    XrdOssCache::Mutex.Lock();
00282    Space.Usage = fsg->Usage; Space.Quota = fsg->Quota;
00283    if ((fsp = XrdOssCache::fsfirst)) do
00284       {if (fsp->fsgroup == fsg)
00285           {fsd = fsp->fsdata; pnum++;
00286            Space.Total += fsd->size;      Space.Free   += fsd->frsz;
00287            if (fsd->frsz > Space.Maxfree) Space.Maxfree = fsd->frsz;
00288            if (fsd->size > Space.Largest) Space.Largest = fsd->size;
00289           }
00290        fsp = fsp->next;
00291       } while(fsp != XrdOssCache::fsfirst);
00292    XrdOssCache::Mutex.UnLock();
00293 
00294 // All done
00295 //
00296    return pnum;
00297 }
00298 
00299 /******************************************************************************/
00300 /*                                A d j u s t                                 */
00301 /******************************************************************************/
00302   
00303 void  XrdOssCache::Adjust(dev_t devid, off_t size)
00304 {
00305    EPNAME("Adjust")
00306    XrdOssCache_FSData *fsdp;
00307    XrdOssCache_Group  *fsgp;
00308 
00309 // Search for matching filesystem
00310 //
00311    fsdp = XrdOssCache::fsdata;
00312    while(fsdp && fsdp->fsid != devid) fsdp = fsdp->next;
00313    if (!fsdp) {DEBUG("dev " <<devid <<" not found."); return;}
00314 
00315 // Find the public cache group (it might not exist)
00316 //
00317    fsgp = XrdOssCache_Group::fsgroups;
00318    while(fsgp && strcmp("public", fsgp->group)) fsgp = fsgp->next;
00319 
00320 // Process the result
00321 //
00322    if (fsdp) 
00323       {DEBUG("free=" <<fsdp->frsz <<'-' <<size <<" path=" <<fsdp->path);
00324        Mutex.Lock();
00325        if (        (fsdp->frsz  -= size) < 0) fsdp->frsz = 0;
00326        fsdp->stat |= XrdOssFSData_ADJUSTED;
00327        if (fsgp && (fsgp->Usage += size) < 0) fsgp->Usage = 0;
00328        Mutex.UnLock();
00329       } else {
00330        DEBUG("dev " <<devid <<" not found.");
00331       }
00332 }
00333 
00334 /******************************************************************************/
00335   
00336 void XrdOssCache::Adjust(const char *Path, off_t size, struct stat *buf)
00337 {
00338    EPNAME("Adjust")
00339    XrdOssCache_FS *fsp;
00340 
00341 // If we have a struct then we need to do some more work
00342 //
00343    if (buf) 
00344       {if ((buf->st_mode & S_IFMT) != S_IFLNK) Adjust(buf->st_dev, size);
00345           else {char lnkbuff[MAXPATHLEN+64];
00346                 int  lnklen = readlink(Path, lnkbuff, sizeof(lnkbuff)-1);
00347                 if (lnklen > 0)
00348                    {XrdOssPath::Trim2Base(lnkbuff+lnklen-1);
00349                     Adjust(lnkbuff, size);
00350                    }
00351                }
00352        return;
00353       }
00354 
00355 // Search for matching logical partition
00356 //
00357    fsp = fsfirst;
00358    while(fsp && strcmp(fsp->path, Path)) 
00359         if ((fsp = fsp->next) == fsfirst) {fsp = 0; break;}
00360 
00361 // Process the result
00362 //
00363    if (fsp) Adjust(fsp, size);
00364       else {DEBUG("cahe path " <<Path <<" not found.");}
00365 }
00366 
00367 /******************************************************************************/
00368   
00369 void XrdOssCache::Adjust(XrdOssCache_FS *fsp, off_t size)
00370 {
00371    EPNAME("Adjust")
00372    XrdOssCache_FSData *fsdp;
00373 
00374 // Process the result
00375 //
00376    if (fsp) 
00377       {fsdp = fsp->fsdata;
00378        DEBUG("used=" <<fsp->fsgroup->Usage <<'+' <<size <<" path=" <<fsp->path);
00379        DEBUG("free=" <<fsdp->frsz <<'-' <<size <<" path=" <<fsdp->path);
00380        Mutex.Lock();
00381        if ((fsp->fsgroup->Usage += size) < 0) fsp->fsgroup->Usage = 0;
00382        if (        (fsdp->frsz  -= size) < 0) fsdp->frsz = 0;
00383        fsdp->stat |= XrdOssFSData_ADJUSTED;
00384        if (Usage) XrdOssSpace::Adjust(fsp->fsgroup->GRPid, size);
00385        Mutex.UnLock();
00386       }
00387 }
00388 
00389 /******************************************************************************/
00390 /*                                 A l l o c                                  */
00391 /******************************************************************************/
00392 
00393 int XrdOssCache::Alloc(XrdOssCache::allocInfo &aInfo)
00394 {
00395    EPNAME("Alloc");
00396    static const mode_t theMode = S_IRWXU | S_IRWXG;
00397    XrdSysMutexHelper myMutex(&Mutex);
00398    double diffree;
00399    XrdOssPath::fnInfo Info;
00400    XrdOssCache_FS *fsp, *fspend, *fsp_sel;
00401    XrdOssCache_Group *cgp = 0;
00402    long long size, maxfree, curfree;
00403    int rc, madeDir, datfd = 0;
00404 
00405 // Compute appropriate allocation size
00406 //
00407    if (!aInfo.cgSize
00408    ||  (size=aInfo.cgSize*ovhAlloc/100+aInfo.cgSize) < minAlloc)
00409       aInfo.cgSize = size = minAlloc;
00410 
00411 // Find the corresponding cache group
00412 //
00413    cgp = XrdOssCache_Group::fsgroups;
00414    while(cgp && strcmp(aInfo.cgName, cgp->group)) cgp = cgp->next;
00415    if (!cgp) return -ENOENT;
00416    fsp = cgp->curr;
00417 
00418 // Find a cache that will fit this allocation request
00419 //
00420    maxfree = fsp->fsdata->frsz;
00421    if (size > maxfree || (aInfo.cgPath && (aInfo.cgPlen > fsp->plen
00422            ||  strncmp(aInfo.cgPath,fsp->path,aInfo.cgPlen)))) fsp_sel = 0;
00423       else fsp_sel = fsp;
00424    fspend = fsp; fsp = fsp->next;
00425    do {
00426        if (strcmp(aInfo.cgName, fsp->group)
00427        || (aInfo.cgPath && (aInfo.cgPlen > fsp->plen
00428                         ||  strncmp(aInfo.cgPath,fsp->path,aInfo.cgPlen)))) continue;
00429        curfree = fsp->fsdata->frsz;
00430        if (size > curfree) continue;
00431 
00432              if (fuzAlloc >= 100) {fsp_sel = fsp; break;}
00433        else  if (!fuzAlloc) {if (curfree > maxfree)
00434                                 {fsp_sel = fsp; maxfree = curfree;}}
00435        else {diffree = (!(curfree + maxfree) ? 0.0
00436                      : static_cast<double>(XRDABS(maxfree - curfree)) /
00437                        static_cast<double>(       maxfree + curfree));
00438              if (diffree > fuzAlloc) {fsp_sel = fsp; maxfree = curfree;}
00439             }
00440       } while((fsp = fsp->next) != fspend);
00441 
00442 // Check if we can realy fit this file. If so, update current scan pointer
00443 //
00444    if (!fsp_sel) return -ENOSPC;
00445    cgp->curr = fsp_sel;
00446 
00447 // Construct the target filename
00448 //
00449    Info.Path    = fsp_sel->path;
00450    Info.Plen    = fsp_sel->plen;
00451    Info.Sfx     = fsp_sel->suffix;
00452    aInfo.cgPsfx = XrdOssPath::genPFN(Info, aInfo.cgPFbf, aInfo.cgPFsz,
00453                   (fsp_sel->opts & XrdOssCache_FS::isXA ? 0 : aInfo.Path));
00454 
00455 // Verify that target name was constructed
00456 //
00457    if (!(*aInfo.cgPFbf)) return -ENAMETOOLONG;
00458 
00459 // Simply open the file in the local filesystem, creating it if need be.
00460 //
00461    if (aInfo.aMode)
00462       {madeDir = 0;
00463        do {do {datfd = open(aInfo.cgPFbf,O_CREAT|O_TRUNC|O_WRONLY,aInfo.aMode);}
00464                while(datfd < 0 && errno == EINTR);
00465            if (datfd >= 0 || errno != ENOENT || madeDir) break;
00466            *Info.Slash='\0'; rc=mkdir(aInfo.cgPFbf,theMode); *Info.Slash='/';
00467            madeDir = 1;
00468           } while(!rc);
00469        if (datfd < 0) return (errno ? -errno : -ENOSYS);
00470       }
00471 
00472 // All done (temporarily adjust down the free space)x
00473 //
00474    DEBUG("free=" <<fsp_sel->fsdata->frsz <<'-' <<size <<" path=" 
00475                  <<fsp_sel->fsdata->path);
00476    fsp_sel->fsdata->frsz -= size;
00477    fsp_sel->fsdata->stat |= XrdOssFSData_REFRESH;
00478    aInfo.cgFSp  = fsp_sel;
00479    return datfd;
00480 }
00481   
00482 /******************************************************************************/
00483 /*                                  F i n d                                   */
00484 /******************************************************************************/
00485   
00486 XrdOssCache_FS *XrdOssCache::Find(const char *Path, int lnklen)
00487 {
00488    XrdOssCache_FS *fsp;
00489    char lnkbuff[MAXPATHLEN+64];
00490    struct stat sfbuff;
00491 
00492 // First see if this is a symlink that refers to a new style cache
00493 //
00494    if (lnklen) 
00495       {if (strlcpy(lnkbuff,Path,sizeof(lnkbuff)) >= sizeof(lnkbuff)) return 0;}
00496       else if (lstat(Path, &sfbuff)
00497            ||  (sfbuff.st_mode & S_IFMT) != S_IFLNK
00498            ||  (lnklen = readlink(Path,lnkbuff,sizeof(lnkbuff)-1)) <= 0)
00499               return 0;
00500 
00501 // Trim the link to the base name
00502 //
00503    XrdOssPath::Trim2Base(lnkbuff+lnklen-1);
00504 
00505 // Search for matching logical partition
00506 //
00507    fsp = fsfirst;
00508    while(fsp && strcmp(fsp->path, lnkbuff))
00509         if ((fsp = fsp->next) == fsfirst) {fsp = 0; break;}
00510    return fsp;
00511 }
00512 
00513 /******************************************************************************/
00514 /*                                  I n i t                                   */
00515 /******************************************************************************/
00516 
00517 // Init() is only called during configuration and no locks are needed.
00518   
00519 int XrdOssCache::Init(const char *UPath, const char *Qfile, int isSOL)
00520 {
00521      XrdOssCache_Group *cgp;
00522      long long bytesUsed;
00523 
00524 // If usage directory or quota file was passed then we initialize space handling
00525 // We need to create a space object to track usage across failures.
00526 //
00527    if ((UPath || Qfile) && !XrdOssSpace::Init(UPath, Qfile, isSOL)) return 1;
00528    if (Qfile) Quotas = !isSOL;
00529    if (UPath) Usage  = 1;
00530 
00531 // If we will be saving space information then we need to assign each group
00532 // to a save set. If there is no space object then skip all of this.
00533 //
00534    if (UPath && (cgp = XrdOssCache_Group::fsgroups))
00535       do {cgp->GRPid = XrdOssSpace::Assign(cgp->group, bytesUsed);
00536           cgp->Usage = bytesUsed;
00537          } while((cgp = cgp->next));
00538    return 0;
00539 }
00540 
00541 /******************************************************************************/
00542 
00543 int XrdOssCache::Init(long long aMin, int ovhd, int aFuzz)
00544 {
00545 // Set values
00546 //
00547    minAlloc = aMin;
00548    ovhAlloc = ovhd;
00549    fuzAlloc = static_cast<double>(aFuzz)/100.0;
00550    return 0;
00551 }
00552 
00553 /******************************************************************************/
00554 /*                                  L i s t                                   */
00555 /******************************************************************************/
00556   
00557 void XrdOssCache::List(const char *lname, XrdSysError &Eroute)
00558 {
00559      XrdOssCache_FS *fsp;
00560      const char *theOpt;
00561      char *pP, buff[4096];
00562 
00563      if ((fsp = fsfirst)) do
00564         {if (fsp->opts & XrdOssCache_FS::isXA)
00565             {pP = (char *)fsp->path + fsp->plen - 1;
00566              do {pP--;} while(*pP != '/');
00567              *pP = '\0';   theOpt = " xa";
00568             } else {pP=0;  theOpt = "";}
00569          snprintf(buff, sizeof(buff), "%s %s %s%s", lname, 
00570                         fsp->group, fsp->path, theOpt);
00571          if (pP) *pP = '/';
00572          Eroute.Say(buff);
00573          fsp = fsp->next;
00574         } while(fsp != fsfirst);
00575 }
00576  
00577 /******************************************************************************/
00578 /*                                 P a r s e                                  */
00579 /******************************************************************************/
00580   
00581 char *XrdOssCache::Parse(const char *token, char *cbuff, int cblen)
00582 {
00583    char *Path;
00584 
00585 // Check for default
00586 //
00587    if (!token || *token == ':')
00588       {strlcpy(cbuff, OSS_CGROUP_DEFAULT, cblen);
00589        return 0;
00590       }
00591 
00592 // Get the correct cache group and partition path
00593 //
00594    if (!(Path = (char *) index(token, ':'))) strlcpy(cbuff, token, cblen);
00595       else {int n = Path - token;
00596             if (n >= cblen) n = cblen-1;
00597             strncpy(cbuff, token, n); cbuff[n] = '\0';
00598             Path++;
00599            }
00600 
00601 // All done
00602 //
00603    return Path;
00604 }
00605 
00606 /******************************************************************************/
00607 /*                                  S c a n                                   */
00608 /******************************************************************************/
00609 
00610 void *XrdOssCache::Scan(int cscanint)
00611 {
00612    EPNAME("CacheScan")
00613    XrdOssCache_FSData *fsdp;
00614    XrdOssCache_Group  *fsgp;
00615    const struct timespec naptime = {cscanint, 0};
00616    long long frsz, llT; // llT is a dummy temporary
00617    int retc, dbgMsg, dbgNoMsg;
00618 
00619 // Try to prevent floodingthe log with scan messages
00620 //
00621    if (cscanint > 0 && cscanint < 60) dbgMsg = cscanint/60;
00622       else dbgMsg = 1;
00623    dbgNoMsg = dbgMsg;
00624 
00625 // Loop scanning the cache
00626 //
00627    while(1)
00628         {if (cscanint > 0) nanosleep(&naptime, 0);
00629 
00630         // Get the cache context lock
00631         //
00632            Mutex.Lock();
00633 
00634         // Scan through all filesystems skip filesystem that have been
00635         // recently adjusted to avoid fs statstics latency problems.
00636         //
00637            fsSize =  0;
00638            fsTotFr=  0;
00639            fsFree =  0;
00640            fsdp = fsdata;
00641            while(fsdp)
00642                 {retc = 0;
00643                  if ((fsdp->stat & XrdOssFSData_REFRESH)
00644                  || !(fsdp->stat & XrdOssFSData_ADJUSTED) || cscanint <= 0)
00645                      {frsz = XrdOssCache_FS::freeSpace(llT,fsdp->path);
00646                       if (frsz < 0) OssEroute.Emsg("CacheScan", errno ,
00647                                     "state file system ",(char *)fsdp->path);
00648                          else {fsdp->frsz = frsz;
00649                                fsdp->stat &= ~(XrdOssFSData_REFRESH |
00650                                                XrdOssFSData_ADJUSTED);
00651                                if (!dbgNoMsg--)
00652                                   {DEBUG("New free=" <<fsdp->frsz <<" path=" <<fsdp->path);
00653                                    dbgNoMsg = dbgMsg;
00654                                   }
00655                                }
00656                      } else fsdp->stat |= XrdOssFSData_REFRESH;
00657                  if (!retc)
00658                     {if (fsdp->frsz > fsFree)
00659                         {fsFree = fsdp->frsz; fsSize = fsdp->size;}
00660                      fsTotFr += fsdp->frsz;
00661                     }
00662                  fsdp = fsdp->next;
00663                 }
00664 
00665         // Unlock the cache and if we have quotas check them out
00666         //
00667            Mutex.UnLock();
00668            if (cscanint <= 0) return (void *)0;
00669            if (Quotas) XrdOssSpace::Quotas();
00670 
00671         // Update usage information if we are keeping track of it
00672            if (Usage && XrdOssSpace::Readjust())
00673               {fsgp = XrdOssCache_Group::fsgroups;
00674                Mutex.Lock();
00675                while(fsgp)
00676                     {fsgp->Usage = XrdOssSpace::Usage(fsgp->GRPid);
00677                      fsgp = fsgp->next;
00678                     }
00679                Mutex.UnLock();
00680               }
00681         }
00682 
00683 // Keep the compiler happy
00684 //
00685    return (void *)0;
00686 }

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