TGFALFile.cxx

Go to the documentation of this file.
00001 // @(#)root/gfal:$Id: TGFALFile.cxx 35358 2010-09-17 09:58:04Z rdm $
00002 // Author: Fons Rademakers   8/12/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TGFALFile                                                            //
00015 //                                                                      //
00016 // A TGFALFile is like a normal TFile except that it reads and writes   //
00017 // its data via the underlaying Grid access mechanism.                  //
00018 // TGFALFile file names are either a logical file name, a guid, an      //
00019 // SURL or a TURL, like:                                                //
00020 //                                                                      //
00021 //    gfal:/lfn/user/r/rdm/galice.root                                  //
00022 //                                                                      //
00023 // Grid storage interactions today require using several existing       //
00024 // software components:                                                 //
00025 //  - The replica catalog services to locate valid replicas of          //
00026 //    files.                                                            //
00027 //  - The SRM software to ensure:                                       //
00028 //     - files  exist on disk (they are recalled from mass              //
00029 //       storage if necessary) or                                       //
00030 //     - space is allocated on disk for new files (they are possibly    //
00031 //       migrated to mass storage later)                                //
00032 //  - A file access mechanism to access files from the storage          //
00033 //    system on the worker node.                                        //
00034 //                                                                      //
00035 // The GFAL library hides these interactions and presents a Posix       //
00036 // interface for the I/O operations. The currently supported protocols  //
00037 // are: file for local access, dcap, gsidcap and kdcap (dCache access   //
00038 // protocol) and rfio (CASTOR access protocol).                         //
00039 //                                                                      //
00040 // File naming convention:                                              //
00041 // A file name can be a Logical File Name (LFN), a Grid Unique          //
00042 // IDentifier (GUID), a file replica (SURL) or a Transport file         //
00043 // name (TURL):                                                         //
00044 //                                                                      //
00045 //     an LFN starts with lfn:                                          //
00046 //        for example lfn:baud/testgfal15                               //
00047 //                                                                      //
00048 //     a GUID starts with guid:                                         //
00049 //        for example guid:2cd59291-7ae7-4778-af6d-b1f423719441         //
00050 //                                                                      //
00051 //     an SURL starts with srm://                                       //
00052 //         for example srm://wacdr002d.cern.ch:8443/castor/             //
00053 //                    cern.ch/user/b/baud/testgfal15                    //
00054 //                                                                      //
00055 //      a TURL starts with a protocol name:                             //
00056 //          for example rfio:///castor/cern.ch/user/b/baud/testgfal15   //
00057 //                                                                      //
00058 // Note that for the TGFALFile plugin to work, all these pathnames      //
00059 // should be prepended by gfal:.                                        //
00060 //                                                                      //
00061 //////////////////////////////////////////////////////////////////////////
00062 
00063 #include "TGFALFile.h"
00064 #include "TROOT.h"
00065 #include "TUrl.h"
00066 
00067 extern "C" {
00068 #include <gfal_api.h>
00069 }
00070 
00071 ClassImp(TGFALFile)
00072 ClassImp(TGFALSystem)
00073 
00074 //______________________________________________________________________________
00075 TGFALFile::TGFALFile(const char *url, Option_t *option, const char *ftitle,
00076                      Int_t compress)
00077          : TFile(url, "NET", ftitle, compress)
00078 {
00079    // Create a GFAL file object. A GFAL file is the same as a TFile
00080    // except that it is being accessed via the underlaying Grid access
00081    // mechanism. The url argument must be of the form: gfal:/lfn/file.root
00082    // If the file specified in the URL does not exist, is not accessable
00083    // or can not be created the kZombie bit will be set in the TGFALFile
00084    // object. Use IsZombie() to see if the file is accessable.
00085    // For a description of the option and other arguments see the TFile ctor.
00086    // The preferred interface to this constructor is via TFile::Open().
00087 
00088    fStatCached = kFALSE;
00089 
00090    fOption = option;
00091    fOption.ToUpper();
00092 
00093    if (fOption == "NEW")
00094       fOption = "CREATE";
00095 
00096    Bool_t create   = (fOption == "CREATE") ? kTRUE : kFALSE;
00097    Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
00098    Bool_t update   = (fOption == "UPDATE") ? kTRUE : kFALSE;
00099    Bool_t read     = (fOption == "READ") ? kTRUE : kFALSE;
00100    if (!create && !recreate && !update && !read) {
00101       read    = kTRUE;
00102       fOption = "READ";
00103    }
00104 
00105    TString stmp;
00106    char *fname;
00107    if ((fname = gSystem->ExpandPathName(fUrl.GetFileAndOptions()))) {
00108       stmp = fname;
00109       delete [] fname;
00110       fname = (char *)stmp.Data();
00111    } else {
00112       Error("TGFALFile", "error expanding path %s", fUrl.GetFileAndOptions());
00113       goto zombie;
00114    }
00115 
00116    if (recreate) {
00117       if (::gfal_access(fname, kFileExists) == 0)
00118          ::gfal_unlink(fname);
00119       recreate = kFALSE;
00120       create   = kTRUE;
00121       fOption  = "CREATE";
00122    }
00123    if (create && ::gfal_access(fname, kFileExists) == 0) {
00124       Error("TGFALFile", "file %s already exists", fname);
00125       goto zombie;
00126    }
00127    if (update) {
00128       if (::gfal_access(fname, kFileExists) != 0) {
00129          update = kFALSE;
00130          create = kTRUE;
00131       }
00132       if (update && ::gfal_access(fname, kWritePermission) != 0) {
00133          Error("TGFALFile", "no write permission, could not open file %s", fname);
00134          goto zombie;
00135       }
00136    }
00137    if (read) {
00138 #ifdef GFAL_ACCESS_FIXED
00139       if (::gfal_access(fname, kFileExists) != 0) {
00140          Error("TGFALFile", "file %s does not exist", fname);
00141          goto zombie;
00142       }
00143       if (::gfal_access(fname, kReadPermission) != 0) {
00144          Error("TGFALFile", "no read permission, could not open file %s", fname);
00145          goto zombie;
00146       }
00147 #endif
00148    }
00149 
00150    // Connect to file system stream
00151    fRealName = fname;
00152 
00153    if (create || update) {
00154 #ifndef WIN32
00155       fD = SysOpen(fname, O_RDWR | O_CREAT, 0644);
00156 #else
00157       fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
00158 #endif
00159       if (fD == -1) {
00160          SysError("TGFALFile", "file %s can not be opened", fname);
00161          goto zombie;
00162       }
00163       fWritable = kTRUE;
00164    } else {
00165 #ifndef WIN32
00166       fD = SysOpen(fname, O_RDONLY, 0644);
00167 #else
00168       fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
00169 #endif
00170       if (fD == -1) {
00171          SysError("TGFALFile", "file %s can not be opened for reading", fname);
00172          goto zombie;
00173       }
00174       fWritable = kFALSE;
00175    }
00176 
00177    Init(create);
00178 
00179    return;
00180 
00181 zombie:
00182    // error in file opening occured, make this object a zombie
00183    MakeZombie();
00184    gDirectory = gROOT;
00185 }
00186 
00187 //______________________________________________________________________________
00188 TGFALFile::~TGFALFile()
00189 {
00190    // GFAL file dtor. Close and flush directory structure.
00191 
00192    Close();
00193 }
00194 
00195 //______________________________________________________________________________
00196 Int_t TGFALFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
00197 {
00198    // Interface to system open. All arguments like in POSIX open.
00199 
00200    Int_t ret = ::gfal_open64(pathname, flags, (Int_t) mode);
00201 
00202    return ret;
00203 }
00204 
00205 //______________________________________________________________________________
00206 Int_t TGFALFile::SysClose(Int_t fd)
00207 {
00208    // Interface to system close. All arguments like in POSIX close.
00209 
00210    Int_t ret = ::gfal_close(fd);
00211 
00212    return ret;
00213 }
00214 
00215 //______________________________________________________________________________
00216 Int_t TGFALFile::SysRead(Int_t fd, void *buf, Int_t len)
00217 {
00218    // Interface to system read. All arguments like in POSIX read.
00219 
00220    Int_t ret = ::gfal_read(fd, buf, len);
00221 
00222    return ret;
00223 }
00224 
00225 //______________________________________________________________________________
00226 Int_t TGFALFile::SysWrite(Int_t fd, const void *buf, Int_t len)
00227 {
00228    // Interface to system write. All arguments like in POSIX write.
00229 
00230    Int_t ret = ::gfal_write(fd, buf, len);
00231 
00232    return ret;
00233 }
00234 
00235 //______________________________________________________________________________
00236 Long64_t TGFALFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
00237 {
00238    // Interface to system lseek. All arguments like in POSIX lseek
00239    // except that the offset and return value are Long_t to be able to
00240    // handle 64 bit file systems.
00241 
00242    Long64_t ret = ::gfal_lseek64(fd, offset, whence);
00243 
00244    return ret;
00245 }
00246 
00247 //______________________________________________________________________________
00248 Int_t TGFALFile::SysStat(Int_t /*fd*/, Long_t *id, Long64_t *size, Long_t *flags,
00249                          Long_t *modtime)
00250 {
00251    // Interface to TSystem:GetPathInfo(). Generally implemented via
00252    // stat() or fstat().
00253 
00254    struct stat64 &statbuf = fStatBuffer;
00255 
00256    if (fOption != "READ" || !fStatCached) {
00257       // We are not in read mode, or the file status information is not yet
00258       // in the cache. Update or read the status information with gfal_stat().
00259 
00260       if (::gfal_stat64(fRealName, &statbuf) >= 0)
00261          fStatCached = kTRUE;
00262    }
00263 
00264    if (fStatCached) {
00265       if (id)
00266          *id = (statbuf.st_dev << 24) + statbuf.st_ino;
00267       if (size)
00268          *size = statbuf.st_size;
00269       if (modtime)
00270          *modtime = statbuf.st_mtime;
00271       if (flags) {
00272          *flags = 0;
00273          if (statbuf.st_mode & ((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
00274             *flags |= 1;
00275          if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
00276             *flags |= 2;
00277          if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
00278              (statbuf.st_mode & S_IFMT) != S_IFDIR)
00279             *flags |= 4;
00280       }
00281       return 0;
00282    }
00283 
00284    return 1;
00285 }
00286 
00287 //______________________________________________________________________________
00288 Bool_t TGFALFile::ReadBuffer(char *buf, Int_t len)
00289 {
00290    // Read specified byte range from remote file via GFAL.
00291    // Returns kTRUE in case of error.
00292 
00293    Int_t st;
00294    if ((st = ReadBufferViaCache(buf, len))) {
00295       if (st == 2)
00296          return kTRUE;
00297       return kFALSE;
00298    }
00299 
00300    return TFile::ReadBuffer(buf, len);
00301 }
00302 
00303 //______________________________________________________________________________
00304 Bool_t TGFALFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
00305 {
00306    // Read specified byte range from remote file via GFAL.
00307    // Returns kTRUE in case of error.
00308 
00309    SetOffset(pos);
00310    Int_t st;
00311    if ((st = ReadBufferViaCache(buf, len))) {
00312       if (st == 2)
00313          return kTRUE;
00314       return kFALSE;
00315    }
00316 
00317    return TFile::ReadBuffer(buf, pos, len);
00318 }
00319 
00320 //______________________________________________________________________________
00321 Bool_t TGFALFile::WriteBuffer(const char *buf, Int_t len)
00322 {
00323    // Write specified byte range to remote file via GFAL.
00324    // Returns kTRUE in case of error.
00325 
00326    if (!IsOpen() || !fWritable) return kTRUE;
00327 
00328    Int_t st;
00329    if ((st = WriteBufferViaCache(buf, len))) {
00330       if (st == 2)
00331          return kTRUE;
00332       return kFALSE;
00333    }
00334 
00335    return TFile::WriteBuffer(buf, len);
00336 }
00337 
00338 
00339 //______________________________________________________________________________
00340 TGFALSystem::TGFALSystem() : TSystem("-gfal", "GFAL Helper System")
00341 {
00342    // Create helper class that allows directory access via GFAL.
00343 
00344    // name must start with '-' to bypass the TSystem singleton check
00345    SetName("gfal");
00346 
00347    fDirp = 0;
00348 }
00349 
00350 //______________________________________________________________________________
00351 Int_t TGFALSystem::MakeDirectory(const char *dir)
00352 {
00353    // Make a directory via GFAL.
00354 
00355    TUrl url(dir);
00356 
00357    Int_t ret = ::gfal_mkdir(url.GetFileAndOptions(), 0755);
00358 
00359    return ret;
00360 }
00361 
00362 //______________________________________________________________________________
00363 void *TGFALSystem::OpenDirectory(const char *dir)
00364 {
00365    // Open a directory via GFAL. Returns an opaque pointer to a dir
00366    // structure. Returns 0 in case of error.
00367 
00368    if (fDirp) {
00369       Error("OpenDirectory", "invalid directory pointer (should never happen)");
00370       fDirp = 0;
00371    }
00372 
00373    TUrl url(dir);
00374 
00375    struct stat64 finfo;
00376 
00377    if (::gfal_stat64(url.GetFileAndOptions(), &finfo) < 0)
00378       return 0;
00379 
00380    if ((finfo.st_mode & S_IFMT) != S_IFDIR)
00381       return 0;
00382 
00383    fDirp = (void*) ::gfal_opendir(url.GetFileAndOptions());
00384 
00385    return fDirp;
00386 }
00387 
00388 //______________________________________________________________________________
00389 void TGFALSystem::FreeDirectory(void *dirp)
00390 {
00391    // Free directory via GFAL.
00392 
00393    if (dirp != fDirp) {
00394       Error("FreeDirectory", "invalid directory pointer (should never happen)");
00395       return;
00396    }
00397 
00398    if (dirp)
00399       ::gfal_closedir((DIR*)dirp);
00400 
00401    fDirp = 0;
00402 }
00403 
00404 //______________________________________________________________________________
00405 const char *TGFALSystem::GetDirEntry(void *dirp)
00406 {
00407    // Get directory entry via GFAL. Returns 0 in case no more entries.
00408 
00409    if (dirp != fDirp) {
00410       Error("GetDirEntry", "invalid directory pointer (should never happen)");
00411       return 0;
00412    }
00413 
00414    struct dirent64 *dp;
00415 
00416    if (dirp) {
00417       dp = ::gfal_readdir64((DIR*)dirp);
00418       if (!dp)
00419          return 0;
00420       return dp->d_name;
00421    }
00422    return 0;
00423 }
00424 
00425 //______________________________________________________________________________
00426 Int_t TGFALSystem::GetPathInfo(const char *path, FileStat_t &buf)
00427 {
00428    // Get info about a file. Info is returned in the form of a FileStat_t
00429    // structure (see TSystem.h).
00430    // The function returns 0 in case of success and 1 if the file could
00431    // not be stat'ed.
00432 
00433    TUrl url(path);
00434 
00435    struct stat64 sbuf;
00436 
00437    if (path && ::gfal_stat64(url.GetFileAndOptions(), &sbuf) >= 0) {
00438 
00439       buf.fDev    = sbuf.st_dev;
00440       buf.fIno    = sbuf.st_ino;
00441       buf.fMode   = sbuf.st_mode;
00442       buf.fUid    = sbuf.st_uid;
00443       buf.fGid    = sbuf.st_gid;
00444       buf.fSize   = sbuf.st_size;
00445       buf.fMtime  = sbuf.st_mtime;
00446       buf.fIsLink = kFALSE;
00447 
00448       return 0;
00449    }
00450    return 1;
00451 }
00452 
00453 //______________________________________________________________________________
00454 Bool_t TGFALSystem::AccessPathName(const char *path, EAccessMode mode)
00455 {
00456    // Returns FALSE if one can access a file using the specified access mode.
00457    // Mode is the same as for the Unix access(2) function.
00458    // Attention, bizarre convention of return value!!
00459 
00460    TUrl url(path);
00461 
00462    if (::gfal_access(url.GetFileAndOptions(), mode) == 0)
00463       return kFALSE;
00464 
00465    return kTRUE;
00466 }

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