XrdOssApi.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                          X r d O s s A p i . c c                           */
00004 /*                                                                            */
00005 /* (c) 2006 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*                DE-AC03-76-SFO0515 with the Deprtment of Energy             */
00009 /******************************************************************************/
00010  
00011 /* These routines are thread-safe if compiled with:
00012    AIX: -D_THREAD_SAFE
00013    SUN: -D_REENTRANT
00014 */
00015 
00016 /******************************************************************************/
00017 /*                             i n c l u d e s                                */
00018 /******************************************************************************/
00019   
00020 #include <unistd.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <signal.h>
00024 #include <strings.h>
00025 #include <stdio.h>
00026 #include <sys/file.h>
00027 #include <sys/stat.h>
00028 #include <sys/types.h>
00029 #include <sys/param.h>
00030 #ifdef __solaris__
00031 #include <sys/vnode.h>
00032 #endif
00033 
00034 #include "XrdVersion.hh"
00035 
00036 #include "XrdOss/XrdOssApi.hh"
00037 #include "XrdOss/XrdOssCache.hh"
00038 #include "XrdOss/XrdOssConfig.hh"
00039 #include "XrdOss/XrdOssError.hh"
00040 #include "XrdOss/XrdOssLock.hh"
00041 #include "XrdOss/XrdOssMio.hh"
00042 #include "XrdOss/XrdOssTrace.hh"
00043 #include "XrdOuc/XrdOucName2Name.hh"
00044 #include "XrdSys/XrdSysError.hh"
00045 #include "XrdSys/XrdSysHeaders.hh"
00046 #include "XrdSys/XrdSysPlatform.hh"
00047 #include "XrdSys/XrdSysPlugin.hh"
00048 
00049 #ifdef XRDOSSCX
00050 #include "oocx_CXFile.h"
00051 #endif
00052 
00053 /******************************************************************************/
00054 /*                  E r r o r   R o u t i n g   O b j e c t                   */
00055 /******************************************************************************/
00056 
00057 XrdOssSys  *XrdOssSS = 0;
00058   
00059 XrdSysError OssEroute(0, "oss_");
00060 
00061 XrdOucTrace OssTrace(&OssEroute);
00062 
00063 /******************************************************************************/
00064 /*           S t o r a g e   S y s t e m   I n s t a n t i a t o r            */
00065 /******************************************************************************/
00066 
00067 char      XrdOssSys::tryMmap = 0;
00068 char      XrdOssSys::chkMmap = 0;
00069 
00070 /******************************************************************************/
00071 /*                XrdOssGetSS (a.k.a. XrdOssGetStorageSystem)                 */
00072 /******************************************************************************/
00073   
00074 // This function is called by the OFS layer to retrieve the Storage System
00075 // object. If a plugin library has been specified, then this function will
00076 // return the object provided by XrdOssGetStorageSystem() within the library.
00077 //
00078 XrdOss *XrdOssGetSS(XrdSysLogger *Logger, const char   *config_fn,
00079                     const char   *OssLib)
00080 {
00081    static XrdOssSys   myOssSys;
00082    extern XrdSysError OssEroute;
00083    XrdSysPlugin    *myLib;
00084    XrdOss          *(*ep)(XrdOss *, XrdSysLogger *, const char *, const char *);
00085    char *parms;
00086 
00087 // If no library has been specified, return the default object
00088 //
00089    if (!OssLib) {if (myOssSys.Init(Logger, config_fn)) return 0;
00090                     else return (XrdOss *)&myOssSys;
00091                 }
00092 
00093 // Find the parms (ignore the constness of the variable)
00094 //
00095    parms = (char *)OssLib;
00096    while(*parms && *parms != ' ') parms++;
00097    if (*parms) *parms++ = '\0';
00098    while(*parms && *parms == ' ') parms++;
00099    if (!*parms) parms = 0;
00100 
00101 // Create a pluin object (we will throw this away without deletion because
00102 // the library must stay open but we never want to reference it again).
00103 //
00104    OssEroute.logger(Logger);
00105    if (!(myLib = new XrdSysPlugin(&OssEroute, OssLib))) return 0;
00106 
00107 // Now get the entry point of the object creator
00108 //
00109    ep = (XrdOss *(*)(XrdOss *, XrdSysLogger *, const char *, const char *))
00110                     (myLib->getPlugin("XrdOssGetStorageSystem"));
00111    if (!ep) return 0;
00112 
00113 // Get the Object now
00114 //
00115    return ep((XrdOss *)&myOssSys, Logger, config_fn, parms);
00116 }
00117  
00118 /******************************************************************************/
00119 /*                      o o s s _ S y s   M e t h o d s                       */
00120 /******************************************************************************/
00121 /******************************************************************************/
00122 /*                                  i n i t                                   */
00123 /******************************************************************************/
00124   
00125 /*
00126   Function: Initialize staging subsystem
00127 
00128   Input:    None
00129 
00130   Output:   Returns zero upon success otherwise (-errno).
00131 */
00132 int XrdOssSys::Init(XrdSysLogger *lp, const char *configfn)
00133 {
00134      int retc;
00135 
00136 // No need to do the herald thing as we are the default storage system
00137 //
00138    OssEroute.logger(lp);
00139 
00140 // Initialize the subsystems
00141 //
00142    XrdOssSS = this;
00143    if ( (retc = Configure(configfn, OssEroute)) ) return retc;
00144 
00145 // All done.
00146 //
00147    return XrdOssOK;
00148 }
00149 
00150 /******************************************************************************/
00151 /*                               L f n 2 P f n                                */
00152 /******************************************************************************/
00153   
00154 int XrdOssSys::Lfn2Pfn(const char *oldp, char *newp, int blen)
00155 {
00156     if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, blen));
00157     if ((int)strlen(oldp) >= blen) return -ENAMETOOLONG;
00158     strcpy(newp, oldp);
00159     return 0;
00160 }
00161 
00162 /******************************************************************************/
00163 /*                          G e n L o c a l P a t h                           */
00164 /******************************************************************************/
00165   
00166 /* GenLocalPath() generates the path that a file will have in the local file
00167    system. The decision is made based on the user-given path (typically what 
00168    the user thinks is the local file system path). The output buffer where the 
00169    new path is placed must be at least MAXPATHLEN bytes long.
00170 */
00171 int XrdOssSys::GenLocalPath(const char *oldp, char *newp)
00172 {
00173     if (lcl_N2N) return -(lcl_N2N->lfn2pfn(oldp, newp, MAXPATHLEN));
00174     if (strlen(oldp) >= MAXPATHLEN) return -ENAMETOOLONG;
00175     strcpy(newp, oldp);
00176     return 0;
00177 }
00178 
00179 /******************************************************************************/
00180 /*                         G e n R e m o t e P a t h                          */
00181 /******************************************************************************/
00182   
00183 /* GenRemotePath() generates the path that a file will have in the remote file
00184    system. The decision is made based on the user-given path (typically what 
00185    the user thinks is the local file system path). The output buffer where the 
00186    new path is placed must be at least MAXPATHLEN bytes long.
00187 */
00188 int XrdOssSys::GenRemotePath(const char *oldp, char *newp)
00189 {
00190     if (rmt_N2N) return -(rmt_N2N->lfn2rfn(oldp, newp, MAXPATHLEN));
00191     if (strlen(oldp) >= MAXPATHLEN) return -ENAMETOOLONG;
00192     strcpy(newp, oldp);
00193     return 0;
00194 }
00195 
00196 /******************************************************************************/
00197 /*                                 C h m o d                                  */
00198 /******************************************************************************/
00199 /*
00200   Function: Change file mode.
00201 
00202   Input:    path        - Is the fully qualified name of the target file.
00203             mode        - The new mode that the file is to have.
00204 
00205   Output:   Returns XrdOssOK upon success and -errno upon failure.
00206 
00207   Notes:    Files are only changed in the local disk cache.
00208 */
00209 
00210 int XrdOssSys::Chmod(const char *path, mode_t mode)
00211 {
00212     char actual_path[MAXPATHLEN+1], *local_path;
00213     int retc;
00214 
00215 // Generate local path
00216 //
00217    if (lcl_N2N)
00218       if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path)))) 
00219          return retc;
00220          else local_path = actual_path;
00221       else local_path = (char *)path;
00222 
00223 // Change the file only in the local filesystem.
00224 //
00225    return (chmod(local_path, mode) ? -errno : XrdOssOK);
00226 }
00227 
00228 /******************************************************************************/
00229 /*                                 M k d i r                                  */
00230 /******************************************************************************/
00231 /*
00232   Function: Create a directory
00233 
00234   Input:    path        - Is the fully qualified name of the new directory.
00235             mode        - The new mode that the directory is to have.
00236             mkpath      - If true, makes the full path.
00237 
00238   Output:   Returns XrdOssOK upon success and -errno upon failure.
00239 
00240   Notes:    Directories are only created in the local disk cache.
00241 */
00242 
00243 int XrdOssSys::Mkdir(const char *path, mode_t mode, int mkpath)
00244 {
00245     char actual_path[MAXPATHLEN+1], *local_path;
00246     int retc;
00247 
00248 // Generate local path
00249 //
00250    if (lcl_N2N)
00251       if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path)))) 
00252          return retc;
00253          else local_path = actual_path;
00254       else local_path = (char *)path;
00255 
00256 // Create the directory or full path only in the loal file system
00257 //
00258    if (!mkdir(local_path, mode))  return XrdOssOK;
00259    if (mkpath && errno == ENOENT) return Mkpath(local_path, mode);
00260                                   return -errno;
00261 }
00262 
00263 /******************************************************************************/
00264 /*                                M k p a t h                                 */
00265 /******************************************************************************/
00266 /*
00267   Function: Create a directory path
00268 
00269   Input:    path        - Is the fully qualified *local* name of the new path.
00270             mode        - The new mode that each new directory is to have.
00271 
00272   Output:   Returns XrdOssOK upon success and -errno upon failure.
00273 
00274   Notes:    Directories are only created in the local disk cache.
00275 */
00276 
00277 int XrdOssSys::Mkpath(const char *path, mode_t mode)
00278 {
00279     char local_path[MAXPATHLEN+1], *next_path;
00280     int  i = strlen(path);
00281 
00282 // Copy the path so we can modify it
00283 //
00284    strcpy(local_path, path);
00285 
00286 // Trim off the trailing slashes so we can have predictable behaviour
00287 //
00288    while(i && local_path[--i] == '/') local_path[i] = '\0';
00289    if (!i) return -ENOENT;
00290 
00291 // Start creating directories starting with the root
00292 //
00293    next_path = local_path;
00294    while((next_path = index(next_path+1, int('/'))))
00295         {*next_path = '\0';
00296          if (mkdir(local_path, mode) && errno != EEXIST) return -errno;
00297          *next_path = '/';
00298         }
00299 
00300 // Create last component and return
00301 //
00302    if (mkdir(local_path, mode) && errno != EEXIST) return -errno;
00303    return XrdOssOK;
00304 }
00305   
00306 
00307 /******************************************************************************/
00308 /*                                 S t a t s                                  */
00309 /******************************************************************************/
00310 
00311 /*
00312   Function: Return statistics.
00313 
00314   Input:    buff        - Buffer where the statistics are to be placed.
00315             blen        - The length of the buffer.
00316 
00317   Output:   Returns number of bytes placed in the buffer less null byte.
00318 */
00319 
00320 int XrdOssSys::Stats(char *buff, int blen)
00321 {
00322    static const char statfmt1[] = "<stats id=\"oss\" v=\"2\">";
00323    static const char statfmt2[] = "</stats>";
00324    static const int  statflen = sizeof(statfmt1) + sizeof(statfmt2);
00325    char *bp = buff;
00326    int n;
00327 
00328 // If only size wanted, return what size we need
00329 //
00330    if (!buff) return statflen + getStats(0,0);
00331 
00332 // Make sure we have enough space
00333 //
00334    if (blen < statflen) return 0;
00335    strcpy(bp, statfmt1);
00336    bp += sizeof(statfmt1)-1; blen -= sizeof(statfmt1)-1;
00337 
00338 // Generate space statistics
00339 //
00340    n = getStats(bp, blen);
00341    bp += n; blen -= n;
00342 
00343 // Add trailer
00344 //
00345    if (blen >= (int)sizeof(statfmt2))
00346       {strcpy(bp, statfmt2); bp += (sizeof(statfmt2)-1);}
00347    return bp - buff;
00348 }
00349   
00350 /******************************************************************************/
00351 /*                              T r u n c a t e                               */
00352 /******************************************************************************/
00353 
00354 /*
00355   Function: Truncate a file.
00356 
00357   Input:    path        - Is the fully qualified name of the target file.
00358             size        - The new size that the file is to have.
00359 
00360   Output:   Returns XrdOssOK upon success and -errno upon failure.
00361 
00362   Notes:    Files are only changed in the local disk cache.
00363 */
00364 
00365 int XrdOssSys::Truncate(const char *path, unsigned long long size)
00366 {
00367     struct stat statbuff;
00368     char actual_path[MAXPATHLEN+1], *local_path;
00369     long long oldsz;
00370     int retc;
00371 
00372 // Generate local path
00373 //
00374    if (lcl_N2N)
00375       if ((retc = lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path)))) 
00376          return retc;
00377          else local_path = actual_path;
00378       else local_path = (char *)path;
00379 
00380 // Get file info to do the correct adjustment
00381 //
00382    if (lstat(local_path, &statbuff)) return -errno;
00383        else if ((statbuff.st_mode & S_IFMT) == S_IFLNK)
00384                {struct stat buff;
00385                 if (stat(local_path, &buff)) return -errno;
00386                 oldsz = buff.st_size;
00387                } else oldsz = statbuff.st_size;
00388 
00389 // Change the file only in the local filesystem and make space adjustemt
00390 //
00391    if (truncate(local_path, size)) return -errno;
00392    XrdOssCache::Adjust(local_path,static_cast<long long>(size)-oldsz,&statbuff);
00393    return XrdOssOK;
00394 }
00395   
00396 /******************************************************************************/
00397 /*                       P r i v a t e   M e t h o d s                        */
00398 /******************************************************************************/
00399 /******************************************************************************/
00400 /*                      o o s s _ D i r   M e t h o d s                       */
00401 /******************************************************************************/
00402 /******************************************************************************/
00403 /*                               o p e n d i r                                */
00404 /******************************************************************************/
00405   
00406 /*
00407   Function: Open the directory `path' and prepare for reading.
00408 
00409   Input:    path      - The fully qualified name of the directory to open.
00410 
00411   Output:   Returns XrdOssOK upon success; (-errno) otherwise.
00412 */
00413 int XrdOssDir::Opendir(const char *dir_path) 
00414 {
00415    EPNAME("Opendir");
00416    char actual_path[MAXPATHLEN+1], *local_path, *remote_path;
00417    int retc;
00418 
00419 // Return an error if this object is already open
00420 //
00421    if (isopen) return -XRDOSS_E8001;
00422 
00423 // Get the processing flags for this directory
00424 //
00425    pflags = XrdOssSS->PathOpts(dir_path);
00426    ateof = 0;
00427 
00428 // Generate local path
00429 //
00430    if (XrdOssSS->lcl_N2N)
00431       if ((retc = XrdOssSS->lcl_N2N->lfn2pfn(dir_path, actual_path, sizeof(actual_path))))
00432          return retc;
00433          else local_path = actual_path;
00434       else local_path = (char *)dir_path;
00435 
00436 // If this is a local filesystem request, open locally.
00437 //
00438    if (!(pflags & XRDEXP_STAGE) || (pflags & XRDEXP_NODREAD))
00439       {TRACE(Opendir, "lcl path " <<local_path <<" (" <<dir_path <<")");
00440        if ((lclfd = opendir((char *)local_path))) {isopen = 1; return XrdOssOK;}
00441        return -errno;
00442       }
00443 
00444 // Generate remote path
00445 //
00446    if (XrdOssSS->rmt_N2N)
00447       if ((retc = XrdOssSS->rmt_N2N->lfn2rfn(dir_path, actual_path, sizeof(actual_path))))
00448          return retc;
00449          else remote_path = actual_path;
00450       else remote_path = (char *)dir_path;
00451 
00452    TRACE(Opendir, "rmt path " << remote_path <<" (" << dir_path <<")");
00453 
00454 // Originally, if MSS directories were not to be read, we ould simply check
00455 // if the path was a directory and return an error if not. That was superceeded
00456 // by making NODREAD mean to read the local directory only (which is not always
00457 // ideal). So, we keep the code below but comment it out for now.
00458 //
00459 // if ((pflags & XRDEXP_NODREAD) && !(pflags & XRDEXP_NOCHECK))
00460 //    {struct stat fstat;
00461 //     if ((retc = XrdOssSS->MSS_Stat(remote_path,&fstat))) return retc;
00462 //     if (!(S_ISDIR(fstat.st_mode))) return -ENOTDIR;
00463 //     isopen = 1;
00464 //     return XrdOssOK;
00465 //    }
00466 
00467 // Open the directory at the remote location.
00468 //
00469    if (!(mssfd = XrdOssSS->MSS_Opendir(remote_path, retc))) return retc;
00470    isopen = 1;
00471    return XrdOssOK;
00472 }
00473 
00474 /******************************************************************************/
00475 /*                               r e a d d i r                                */
00476 /******************************************************************************/
00477 
00478 /*
00479   Function: Read the next entry if directory associated with this object.
00480 
00481   Input:    buff       - Is the address of the buffer that is to hold the next
00482                          directory name.
00483             blen       - Size of the buffer.
00484 
00485   Output:   Upon success, places the contents of the next directory entry
00486             in buff. When the end of the directory is encountered buff
00487             will be set to the null string.
00488 
00489             Upon failure, returns a (-errno).
00490 
00491   Warning: The caller must provide proper serialization.
00492 */
00493 int XrdOssDir::Readdir(char *buff, int blen)
00494 {
00495    struct dirent *rp;
00496 
00497 // Check if this object is actually open
00498 //
00499    if (!isopen) return -XRDOSS_E8002;
00500 
00501 // Perform local reads if this is a local directory
00502 //
00503    if (lclfd)
00504       {errno = 0;
00505        if ((rp = readdir(lclfd)))
00506           {strlcpy(buff, rp->d_name, blen);
00507            return XrdOssOK;
00508           }
00509        *buff = '\0'; ateof = 1;
00510        return -errno;
00511       }
00512 
00513 // Simulate the read operation, if need be.
00514 //
00515    if (pflags & XRDEXP_NODREAD)
00516       {if (ateof) *buff = '\0';
00517           else   {*buff = '.'; ateof = 1;}
00518        return XrdOssOK;
00519       }
00520 
00521 // Perform a remote read
00522 //
00523    return XrdOssSS->MSS_Readdir(mssfd, buff, blen);
00524 }
00525 
00526 /******************************************************************************/
00527 /*                                 C l o s e                                  */
00528 /******************************************************************************/
00529   
00530 /*
00531   Function: Close the directory associated with this object.
00532 
00533   Input:    None.
00534 
00535   Output:   Returns XrdOssOK upon success and (errno) upon failure.
00536 */
00537 int XrdOssDir::Close(long long *retsz)
00538 {
00539     int retc;
00540 
00541 // Make sure this object is open
00542 //
00543     if (!isopen) return -XRDOSS_E8002;
00544 
00545 // Close whichever handle is open
00546 //
00547     if (lclfd) {if (!(retc = closedir(lclfd))) lclfd = 0;}
00548        else if (mssfd) { if (!(retc = XrdOssSS->MSS_Closedir(mssfd))) mssfd = 0;}
00549                else retc = 0;
00550 
00551 // Indicate whether or not we really closed this object
00552 //
00553    return retc;
00554 }
00555 
00556 /******************************************************************************/
00557 /*                     o o s s _ F i l e   M e t h o d s                      */
00558 /******************************************************************************/
00559   
00560 /******************************************************************************/
00561 /*                                  o p e n                                   */
00562 /******************************************************************************/
00563 
00564 /*
00565   Function: Open the file `path' in the mode indicated by `Mode'.
00566 
00567   Input:    path      - The fully qualified name of the file to open.
00568             Oflag     - Standard open flags.
00569             Mode      - Create mode (i.e., rwx).
00570             env       - Environmental information.
00571 
00572   Output:   XrdOssOK upon success; -errno otherwise.
00573 */
00574 int XrdOssFile::Open(const char *path, int Oflag, mode_t Mode, XrdOucEnv &Env)
00575 {
00576    unsigned long long popts;
00577    int retc, mopts;
00578    char actual_path[MAXPATHLEN+1], *local_path;
00579    struct stat buf;
00580 
00581 // Return an error if this object is already open
00582 //
00583    if (fd >= 0) return -XRDOSS_E8003;
00584       else cxobj = 0;
00585 
00586 // Construct the processing options for this path
00587 //
00588    popts = XrdOssSS->PathOpts(path);
00589 
00590 // Generate local path
00591 //
00592    if (XrdOssSS->lcl_N2N)
00593       if ((retc = XrdOssSS->lcl_N2N->lfn2pfn(path, actual_path, sizeof(actual_path))))
00594          return retc;
00595          else local_path = actual_path;
00596       else local_path = (char *)path;
00597 
00598 // Check if this is a read/only filesystem
00599 //
00600    if ((Oflag & (O_WRONLY | O_RDWR)) && (popts & XRDEXP_NOTRW))
00601       {if (popts & XRDEXP_FORCERO) Oflag = O_RDONLY;
00602           else return OssEroute.Emsg("Open",-XRDOSS_E8005,"open r/w",path);
00603       }
00604 
00605 // If we can open the local copy. If not found, try to stage it in if possible.
00606 // Note that stage will regenerate the right local and remote paths.
00607 //
00608    if ( (fd = (int)Open_ufs(local_path, Oflag, Mode, popts)) == -ENOENT
00609    && (popts & XRDEXP_REMOTE))
00610       {if (!(popts & XRDEXP_STAGE))
00611           return OssEroute.Emsg("Open",-XRDOSS_E8006,"open",path);
00612        if ((retc = XrdOssSS->Stage(tident, path, Env, Oflag, Mode, popts)))
00613           return retc;
00614        fd = (int)Open_ufs(local_path, Oflag, Mode, popts & ~XRDEXP_REMOTE);
00615       }
00616 
00617 // This interface supports only regular files. Complain if this is not one.
00618 //
00619    if (fd >= 0)
00620       {do {retc = fstat(fd, &buf);} while(retc && errno == EINTR);
00621        if (!retc && !(buf.st_mode & S_IFREG))
00622           {close(fd); fd = (buf.st_mode & S_IFDIR ? -EISDIR : -ENOTBLK);}
00623        if (Oflag & (O_WRONLY | O_RDWR))
00624           {FSize = buf.st_size; cacheP = XrdOssCache::Find(local_path);}
00625           else {if (buf.st_mode & S_ISUID && fd >= 0) {close(fd); fd=-ETXTBSY;}
00626                 FSize = -1; cacheP = 0;
00627                }
00628       } else if (fd == -EEXIST)
00629                 {do {retc = stat(local_path,&buf);} while(retc && errno==EINTR);
00630                  if (!retc && (buf.st_mode & S_IFDIR)) fd = -EISDIR;
00631                 }
00632 
00633 // See if should memory map this file
00634 //
00635    if (fd >= 0 && XrdOssSS->tryMmap)
00636       {mopts = 0;
00637        if (popts & XRDEXP_MKEEP) mopts |= OSSMIO_MPRM;
00638        if (popts & XRDEXP_MLOK)  mopts |= OSSMIO_MLOK;
00639        if (popts & XRDEXP_MMAP)  mopts |= OSSMIO_MMAP;
00640        if (XrdOssSS->chkMmap) mopts = XrdOssMio::getOpts(local_path, mopts);
00641        if (mopts) mmFile = XrdOssMio::Map(local_path, fd, mopts);
00642       } else mmFile = 0;
00643 
00644 // Return the result of this open
00645 //
00646    return (fd < 0 ? fd : XrdOssOK);
00647 }
00648 
00649 /******************************************************************************/
00650 /*                                 c l o s e                                  */
00651 /******************************************************************************/
00652 
00653 /*
00654   Function: Close the file associated with this object.
00655 
00656   Input:    None.
00657 
00658   Output:   Returns XrdOssOK upon success and -1 upon failure.
00659 */
00660 int XrdOssFile::Close(long long *retsz)
00661 {
00662     if (fd < 0) return -XRDOSS_E8004;
00663     if (retsz || cacheP)
00664        {struct stat buf;
00665         int retc;
00666         do {retc = fstat(fd, &buf);} while(retc && errno == EINTR);
00667         if (cacheP && FSize != buf.st_size)
00668            XrdOssCache::Adjust(cacheP, buf.st_size - FSize);
00669         if (retsz) *retsz = buf.st_size;
00670        }
00671     if (close(fd)) return -errno;
00672     if (mmFile) {XrdOssMio::Recycle(mmFile); mmFile = 0;}
00673 #ifdef XRDOSSCX
00674     if (cxobj) {delete cxobj; cxobj = 0;}
00675 #endif
00676     fd = -1; FSize = -1; cacheP = 0;
00677     return XrdOssOK;
00678 }
00679 
00680 /******************************************************************************/
00681 /*                                  r e a d                                   */
00682 /******************************************************************************/
00683 
00684 /*
00685   Function: Preread `blen' bytes from the associated file.
00686 
00687   Input:    offset    - The absolute 64-bit byte offset at which to read.
00688             blen      - The size to preread.
00689 
00690   Output:   Returns zero read upon success and -errno upon failure.
00691 */
00692 
00693 ssize_t XrdOssFile::Read(off_t offset, size_t blen)
00694 {
00695 
00696      if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00697 
00698      return 0;  // We haven't implemented this yet!
00699 }
00700 
00701 
00702 /******************************************************************************/
00703 /*                                  r e a d                                   */
00704 /******************************************************************************/
00705 
00706 /*
00707   Function: Read `blen' bytes from the associated file, placing in 'buff'
00708             the data and returning the actual number of bytes read.
00709 
00710   Input:    buff      - Address of the buffer in which to place the data.
00711             offset    - The absolute 64-bit byte offset at which to read.
00712             blen      - The size of the buffer. This is the maximum number
00713                         of bytes that will be read.
00714 
00715   Output:   Returns the number bytes read upon success and -errno upon failure.
00716 */
00717 
00718 ssize_t XrdOssFile::Read(void *buff, off_t offset, size_t blen)
00719 {
00720      ssize_t retval;
00721 
00722      if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00723 
00724 #ifdef XRDOSSCX
00725      if (cxobj)  
00726         if (XrdOssSS->DirFlags & XrdOssNOSSDEC) return (ssize_t)-XRDOSS_E8021;
00727            else   retval = cxobj->Read((char *)buff, blen, offset);
00728         else 
00729 #endif
00730              do { retval = pread(fd, buff, blen, offset); }
00731                 while(retval < 0 && errno == EINTR);
00732 
00733      return (retval >= 0 ? retval : (ssize_t)-errno);
00734 }
00735 
00736 /******************************************************************************/
00737 /*                               R e a d R a w                                */
00738 /******************************************************************************/
00739 
00740 /*
00741   Function: Read `blen' bytes from the associated file, placing in 'buff'
00742             the data and returning the actual number of bytes read.
00743 
00744   Input:    buff      - Address of the buffer in which to place the data.
00745             offset    - The absolute 64-bit byte offset at which to read.
00746             blen      - The size of the buffer. This is the maximum number
00747                         of bytes that will be read.
00748 
00749   Output:   Returns the number bytes read upon success and -errno upon failure.
00750 */
00751 
00752 ssize_t XrdOssFile::ReadRaw(void *buff, off_t offset, size_t blen)
00753 {
00754      ssize_t retval;
00755 
00756      if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00757 
00758 #ifdef XRDOSSCX
00759      if (cxobj)   retval = cxobj->ReadRaw((char *)buff, blen, offset);
00760         else 
00761 #endif
00762              do { retval = pread(fd, buff, blen, offset); }
00763                 while(retval < 0 && errno == EINTR);
00764 
00765      return (retval >= 0 ? retval : (ssize_t)-errno);
00766 }
00767 
00768 /******************************************************************************/
00769 /*                                 w r i t e                                  */
00770 /******************************************************************************/
00771 
00772 /*
00773   Function: Write `blen' bytes to the associated file, from 'buff'
00774             and return the actual number of bytes written.
00775 
00776   Input:    buff      - Address of the buffer from which to get the data.
00777             offset    - The absolute 64-bit byte offset at which to write.
00778             blen      - The number of bytes to write from the buffer.
00779 
00780   Output:   Returns the number of bytes written upon success and -errno o/w.
00781 */
00782 
00783 ssize_t XrdOssFile::Write(const void *buff, off_t offset, size_t blen)
00784 {
00785      ssize_t retval;
00786 
00787      if (fd < 0) return (ssize_t)-XRDOSS_E8004;
00788 
00789      if (XrdOssSS->MaxSize && (long long)(offset+blen) > XrdOssSS->MaxSize)
00790         return (ssize_t)-XRDOSS_E8007;
00791 
00792      do { retval = pwrite(fd, buff, blen, offset); }
00793           while(retval < 0 && errno == EINTR);
00794 
00795      if (retval < 0) retval = (retval == EBADF && cxobj ? -XRDOSS_E8022 : -errno);
00796      return retval;
00797 }
00798 
00799 /******************************************************************************/
00800 /*                                F c h m o d                                 */
00801 /******************************************************************************/
00802 
00803 /*
00804   Function: Sets mode bits for an open file.
00805 
00806   Input:    Mode      - The mode to set.
00807 
00808   Output:   Returns XrdOssOK upon success and -errno upon failure.
00809 */
00810 
00811 int XrdOssFile::Fchmod(mode_t Mode)
00812 {
00813     return (fchmod(fd, Mode) ? -errno : XrdOssOK);
00814 }
00815   
00816 /******************************************************************************/
00817 /*                                 F s t a t                                  */
00818 /******************************************************************************/
00819 
00820 /*
00821   Function: Return file status for the associated file.
00822 
00823   Input:    buff      - Pointer to buffer to hold file status.
00824 
00825   Output:   Returns XrdOssOK upon success and -errno upon failure.
00826 */
00827 
00828 int XrdOssFile::Fstat(struct stat *buff)
00829 {
00830     return (fstat(fd, buff) ? -errno : XrdOssOK);
00831 }
00832 
00833 /******************************************************************************/
00834 /*                               F s y n c                                    */
00835 /******************************************************************************/
00836 
00837 /*
00838   Function: Synchronize associated file.
00839 
00840   Input:    None.
00841 
00842   Output:   Returns XrdOssOK upon success and -errno upon failure.
00843 */
00844 int XrdOssFile::Fsync(void)
00845 {
00846     return (fsync(fd) ? -errno : XrdOssOK);
00847 }
00848 
00849 /******************************************************************************/
00850 /*                               g e t M m a p                                */
00851 /******************************************************************************/
00852   
00853 /*
00854   Function: Indicate whether or not file is memory mapped.
00855 
00856   Input:    addr      - Points to an address which will receive the location
00857                         memory where the file is mapped. If the address is
00858                         null, true is returned if a mapping exist.
00859 
00860   Output:   Returns the size of the file if it is memory mapped (see above).
00861             Otherwise, zero is returned and addr is set to zero.
00862 */
00863 off_t XrdOssFile::getMmap(void **addr)
00864 {
00865    if (mmFile) return (addr ? mmFile->Export(addr) : 1);
00866    if (addr) *addr = 0;
00867    return 0;
00868 }
00869   
00870 /******************************************************************************/
00871 /*                          i s C o m p r e s s e d                           */
00872 /******************************************************************************/
00873   
00874 /*
00875   Function: Indicate whether or not file is compressed.
00876 
00877   Input:    cxidp     - Points to a four byte buffer to hold the compression
00878                         algorithm used if the file is compressed or null.
00879 
00880   Output:   Returns the regios size which is 0 if the file is not compressed.
00881             If cxidp is not null, the algorithm is returned only if the file
00882             is compressed.
00883 */
00884 int XrdOssFile::isCompressed(char *cxidp)
00885 {
00886     if (cxpgsz)
00887        {cxidp[0] = cxid[0]; cxidp[1] = cxid[1];
00888         cxidp[2] = cxid[2]; cxidp[3] = cxid[3];
00889        }
00890     return cxpgsz;
00891 }
00892 
00893 /******************************************************************************/
00894 /*                              t r u n c a t e                               */
00895 /******************************************************************************/
00896 
00897 /*
00898   Function: Set the length of associated file to 'flen'.
00899 
00900   Input:    flen      - The new size of the file. Only 32-bit lengths
00901                         are supported.
00902 
00903   Output:   Returns XrdOssOK upon success and -1 upon failure.
00904 
00905   Notes:    If 'flen' is smaller than the current size of the file, the file
00906             is made smaller and the data past 'flen' is discarded. If 'flen'
00907             is larger than the current size of the file, a hole is created
00908             (i.e., the file is logically extended by filling the extra bytes 
00909             with zeroes).
00910 
00911             If compiled w/o large file support, only lower 32 bits are used.
00912             used.
00913             in supporting it for any other system.
00914 */
00915 int XrdOssFile::Ftruncate(unsigned long long flen) {
00916     off_t newlen = flen;
00917 
00918     if (sizeof(newlen) < sizeof(flen) && (flen>>31)) return -XRDOSS_E8008;
00919 
00920 // Note that space adjustment will occur when the file is closed, not here
00921 //
00922     return (ftruncate(fd, newlen) ?  -errno : XrdOssOK);
00923     }
00924 
00925 /******************************************************************************/
00926 /*                     P R I V A T E    S E C T I O N                         */
00927 /******************************************************************************/
00928 /******************************************************************************/
00929 /*                      o o s s _ O p e n _ u f s                             */
00930 /******************************************************************************/
00931 
00932 int XrdOssFile::Open_ufs(const char *path, int Oflag, int Mode, 
00933                          unsigned long long popts)
00934 {
00935     EPNAME("Open_ufs")
00936     static const int isWritable = O_WRONLY|O_RDWR;
00937     int myfd, newfd, retc;
00938 #ifndef NODEBUG
00939     char *ftype = (char *)" path=";
00940 #endif
00941     XrdOssLock ufs_file;
00942 #ifdef XRDOSSCX
00943     int attcx = 0;
00944 #endif
00945 
00946 // Obtain exclusive control over the directory.
00947 //
00948     if ((popts & XRDEXP_REMOTE)
00949     && (retc = ufs_file.Serialize(path, XrdOssDIR|XrdOssEXC)) < 0) return retc;
00950 
00951 // Now open the actual data file in the appropriate mode.
00952 //
00953     do { myfd = open(path, Oflag|O_LARGEFILE, Mode);}
00954        while( myfd < 0 && errno == EINTR);
00955 
00956 // If the file is marked purgeable or migratable and we may modify this file,
00957 // then get a shared lock on the file to keep it from being migrated or purged
00958 // while it is open.
00959 //
00960    if (popts & XRDEXP_PURGE || (popts & XRDEXP_MIG && Oflag & isWritable))
00961       ufs_file.Serialize(myfd, XrdOssSHR);
00962 
00963 // Chck if file is compressed
00964 //
00965     if (myfd < 0) myfd = -errno;
00966 #ifdef XRDOSSCX
00967        else if ((popts & XRDEXP_COMPCHK)
00968             && oocx_CXFile::isCompressed(myfd, cxid, &cxpgsz)) 
00969                if (Oflag != O_RDONLY) {close(myfd); return -XRDOSS_E8022;}
00970                   else attcx = 1;
00971 #endif
00972 
00973 // Relocate the file descriptor if need be and make sure file is closed on exec
00974 //
00975     if (myfd >= 0)
00976        {if (myfd < XrdOssSS->FDFence)
00977            {if ((newfd = fcntl(myfd, F_DUPFD, XrdOssSS->FDFence)) < 0)
00978                OssEroute.Emsg("Open_ufs",errno,"reloc FD",path);
00979                else {close(myfd); myfd = newfd;}
00980            }
00981         fcntl(myfd, F_SETFD, FD_CLOEXEC);
00982 #ifdef XRDOSSCX
00983         // If the file is compressed get a CXFile object and attach the FD to it
00984         //
00985         if (attcx) {cxobj = new oocx_CXFile;
00986                     ftype = (char *)" CXpath=";
00987                     if ((retc = cxobj->Attach(myfd, path)) < 0)
00988                        {close(myfd); myfd = retc; delete cxobj; cxobj = 0;}
00989                    }
00990 #endif
00991        }
00992 
00993 // Trace the action.
00994 //
00995     TRACE(Open, "fd=" <<myfd <<" flags=" <<std::hex <<Oflag <<" mode="
00996                 <<std::oct <<Mode <<std::dec <<ftype <<path);
00997 
00998 // Deserialize the directory and return the result.
00999 //
01000     if (popts & XRDEXP_REMOTE) ufs_file.UnSerialize(0);
01001     return myfd;
01002 }

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