XrdOssCreate.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                       X r d O s s C r e a t 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: XrdOssCreate.cc 34000 2010-06-21 06:49:56Z ganis $
00012 
00013 const char *XrdOssCreateCVSID = "$Id: XrdOssCreate.cc 34000 2010-06-21 06:49:56Z ganis $";
00014 
00015 /******************************************************************************/
00016 /*                             i n c l u d e s                                */
00017 /******************************************************************************/
00018   
00019 #include <unistd.h>
00020 #include <errno.h>
00021 #include <fcntl.h>
00022 #include <strings.h>
00023 #include <stdio.h>
00024 #include <sys/file.h>
00025 #include <sys/stat.h>
00026 #include <sys/types.h>
00027 #include <sys/param.h>
00028 #if defined(__solaris__) || defined(AIX)
00029 #include <sys/vnode.h>
00030 #endif
00031 
00032 #include "XrdOss/XrdOssApi.hh"
00033 #include "XrdOss/XrdOssCache.hh"
00034 #include "XrdOss/XrdOssConfig.hh"
00035 #include "XrdOss/XrdOssCopy.hh"
00036 #include "XrdOss/XrdOssError.hh"
00037 #include "XrdOss/XrdOssLock.hh"
00038 #include "XrdOss/XrdOssOpaque.hh"
00039 #include "XrdOss/XrdOssPath.hh"
00040 #include "XrdOss/XrdOssSpace.hh"
00041 #include "XrdOss/XrdOssTrace.hh"
00042 #include "XrdOuc/XrdOuca2x.hh"
00043 #include "XrdOuc/XrdOucEnv.hh"
00044 #include "XrdOuc/XrdOucExport.hh"
00045 #include "XrdOuc/XrdOucUtils.hh"
00046 #include "XrdSys/XrdSysError.hh"
00047 #include "XrdSys/XrdSysHeaders.hh"
00048 #include "XrdSys/XrdSysPlatform.hh"
00049 
00050 /******************************************************************************/
00051 /*                  E r r o r   R o u t i n g   O b j e c t                   */
00052 /******************************************************************************/
00053   
00054 extern XrdSysError OssEroute;
00055 
00056 extern XrdOucTrace OssTrace;
00057 
00058 extern XrdOssSys  *XrdOssSS;
00059 
00060 /******************************************************************************/
00061 /*                                c r e a t e                                 */
00062 /******************************************************************************/
00063 
00064 /*
00065   Function: Create a file named `path' with 'file_mode' access mode bits set.
00066 
00067   Input:    path        - The fully qualified name of the file to create.
00068             access_mode - The Posix access mode bits to be assigned to the file.
00069                           These bits correspond to the standard Unix permission
00070                           bits (e.g., 744 == "rwxr--r--").
00071             env         - Environmental information.
00072             opts        - Set as follows:
00073                           XRDOSS_mkpath - create dir path if it does not exist.
00074                           XRDOSS_new    - the file must not already exist.
00075                           x00000000     - x are standard open flags (<<8)
00076 
00077   Output:   Returns XRDOSS_OK upon success; (-errno) otherwise.
00078 */
00079 int XrdOssSys::Create(const char *tident, const char *path, mode_t access_mode,
00080                       XrdOucEnv &env, int Opts)
00081 {
00082     EPNAME("Create")
00083     const int LKFlags = XrdOssFILE|XrdOssSHR|XrdOssNOWAIT|XrdOssRETIME;
00084     const int AMode = S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH; // 775
00085     char  local_path[MAXPATHLEN+1], *p, pc;
00086     unsigned long long popts, remotefs;
00087     int isLink = 0, Missing = 1, retc = 0, datfd;
00088     XrdOssLock path_dir, new_file;
00089     struct stat buf;
00090 
00091 // Get options associated with this path and check if it's r/w
00092 //
00093    remotefs = Check_RO(Create, popts, path, "create");
00094 
00095 // Generate the actual local path for this file.
00096 //
00097    if ((retc = GenLocalPath(path, local_path))) return retc;
00098 
00099 // Determine the state of the file. We will need this information as we go on.
00100 //
00101    if ((Missing = lstat(local_path, &buf))) retc = errno;
00102       else {if ((isLink = ((buf.st_mode & S_IFMT) == S_IFLNK)))
00103                {if (stat(local_path, &buf))
00104                    {if (errno != ENOENT) return -errno;
00105                     OssEroute.Emsg("Create","removing dangling link",local_path);
00106                     if (unlink(local_path)) retc = errno;
00107                     Missing = 1; isLink = 0;
00108                    }
00109                }
00110             }
00111    if (retc && retc != ENOENT) return -retc;
00112 
00113 // At this point, creation requests may need to be routed via the stagecmd.
00114 // This is done if the file/link do not exist. Otherwise, we drop through.
00115 //
00116    if (StageCreate && Missing)
00117       return XrdOssSS->Stage(tident, path, env, Opts>>8, access_mode, popts);
00118 
00119 // The file must not exist if it's declared "new". Otherwise, reuse the space.
00120 //
00121    if (!Missing)
00122       {if (Opts & XRDOSS_new)                 return -EEXIST;
00123        if ((buf.st_mode & S_IFMT) == S_IFDIR) return -EISDIR;
00124        do {datfd = open(local_path, Opts>>8, access_mode);}
00125                    while(datfd < 0 && errno == EINTR);
00126            if (datfd < 0) return -errno;
00127        close(datfd);
00128        if (Opts>>8 & O_TRUNC && buf.st_size)
00129           {off_t theSize = buf.st_size;
00130            if (isLink) {buf.st_mode = (buf.st_mode & ~S_IFMT) | S_IFLNK;
00131                         XrdOssCache::Adjust(local_path, -theSize, &buf);
00132                        }
00133           }
00134        return 0;
00135       }
00136 
00137 // If the path is to be created, make sure the path exists at this point
00138 //
00139    if ((Opts & XRDOSS_mkpath) && (p = rindex(local_path, '/')))
00140       {p++; pc = *p; *p = '\0';
00141        XrdOucUtils::makePath(local_path, AMode);
00142        *p = pc;
00143       }
00144 
00145 // If this is a staging filesystem then we have lots more work to do.
00146 //
00147    if (remotefs)
00148       {char remote_path[MAXPATHLEN+1];
00149 
00150       // Generate the remote path for this file
00151       //
00152          if ((retc = GenRemotePath(path,remote_path))) return retc;
00153 
00154       // Gain exclusive control over the directory.
00155       //
00156          if ( (retc = path_dir.Serialize(local_path, XrdOssDIR|XrdOssEXC)) < 0)
00157             return retc;
00158 
00159      // Create the file in remote system unless not wanted so
00160      //
00161         if (popts & XRDEXP_RCREATE)
00162            {if ((retc = MSS_Create(remote_path, access_mode, env)) < 0)
00163                {path_dir.UnSerialize(0);
00164                 DEBUG("rc" <<retc <<" mode=" <<std::oct <<access_mode
00165                            <<std::dec <<" remote path=" <<remote_path);
00166                 return retc;
00167                }
00168            } else if (!(popts & XRDEXP_NOCHECK))
00169                      {if (!(retc = MSS_Stat(remote_path)))
00170                          {path_dir.UnSerialize(0); return -EEXIST;}
00171                          else if (retc != -ENOENT)
00172                                  {path_dir.UnSerialize(0); return retc;}
00173                      }
00174       }
00175 
00176 // Created file in the extended cache or the local name space
00177 //
00178    if (XrdOssCache::fsfirst && !(popts & XRDEXP_INPLACE))
00179            retc = Alloc_Cache(local_path, access_mode, env);
00180       else retc = Alloc_Local(local_path, access_mode, env);
00181 
00182 // If successful, appropriately manage the locks.
00183 //
00184    if (retc == XrdOssOK && (popts & XRDEXP_MAKELF))
00185       if (new_file.Serialize(local_path,LKFlags) >= 0) new_file.UnSerialize(0);
00186 
00187 // All done.
00188 //
00189    if (remotefs) path_dir.UnSerialize(0);
00190    return retc;
00191 }
00192   
00193 /******************************************************************************/
00194 /*                       P r i v a t e   M e t h o d s                        */
00195 /******************************************************************************/
00196 /******************************************************************************/
00197 /*                           A l l o c _ C a c h e                            */
00198 /******************************************************************************/
00199 
00200 int XrdOssSys::Alloc_Cache(const char *path, mode_t amode, XrdOucEnv &env)
00201 {
00202    EPNAME("Alloc_Cache")
00203    int datfd;
00204    char pbuff[MAXPATHLEN+1], cgbuff[XrdOssSpace::minSNbsz], *tmp;
00205    XrdOssCache::allocInfo aInfo(path, pbuff, sizeof(pbuff));
00206 
00207 // Grab the suggested size from the environment
00208 //
00209    if ((tmp = env.Get(OSS_ASIZE))
00210    &&  !XrdOuca2x::a2ll(OssEroute,"invalid asize",tmp,&aInfo.cgSize,0))
00211       return -XRDOSS_E8018;
00212 
00213 // Get the correct cache group and partition path
00214 //
00215    if ((aInfo.cgPath=XrdOssCache::Parse(env.Get(OSS_CGROUP),cgbuff,sizeof(cgbuff))))
00216       aInfo.cgPlen = strlen(aInfo.cgPath);
00217 
00218 // Allocate space in the cache.
00219 //
00220    aInfo.cgName = cgbuff;
00221    aInfo.aMode  = amode;
00222    if ((datfd = XrdOssCache::Alloc(aInfo)) < 0) return datfd;
00223    close(datfd);
00224 
00225 // Now create a symbolic link to the target
00226 //
00227    if ((symlink(pbuff, path) && errno != EEXIST)
00228    ||  unlink(path) || symlink(pbuff, path)) {datfd = -errno; unlink(pbuff);}
00229 
00230 // Now create a symlink from the cache pfn to the actual path (xa only)
00231 //
00232    if (aInfo.cgPsfx)
00233       {strcpy(aInfo.cgPsfx, ".pfn");
00234        if ((symlink(path, pbuff) && errno != EEXIST)
00235        ||  unlink(pbuff) || symlink(path, pbuff)) datfd = -errno;
00236        *(aInfo.cgPsfx) = '\0';
00237        if (datfd < 0) {unlink(pbuff); unlink(path);}
00238       }
00239 
00240 // All done
00241 //
00242    DEBUG(aInfo.cgName <<" cache for " <<pbuff);
00243    return (datfd >= 0 ? XrdOssOK : datfd);
00244 }
00245 
00246 /******************************************************************************/
00247 /*                           A l l o c _ L o c a l                            */
00248 /******************************************************************************/
00249 
00250 int XrdOssSys::Alloc_Local(const char *path, mode_t amode, XrdOucEnv &env)
00251 {
00252    int datfd;
00253 
00254 // Simply open the file in the local filesystem, creating it if need be.
00255 //
00256    do {datfd = open(path, O_CREAT|O_TRUNC, amode);}
00257                while(datfd < 0 && errno == EINTR);
00258    if (datfd < 0) return -errno;
00259    close(datfd);
00260    return XrdOssOK;
00261 }

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