XrdFrmAdminReloc.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                   X r d F r m A d m i n R e l o c . c c                    */
00004 /*                                                                            */
00005 /* (c) 2008 by the Board of Trustees of the Leland Stanford, Jr., University  */
00006 /*                            All Rights Reserved                             */
00007 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00008 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00009 /******************************************************************************/
00010   
00011 //          $Id: XrdFrmAdminReloc.cc 35287 2010-09-14 21:19:35Z ganis $
00012 
00013 const char *XrdFrmAdminRelockCVSID = "$Id: XrdFrmAdminReloc.cc 35287 2010-09-14 21:19:35Z ganis $";
00014 
00015 #include <errno.h>
00016 #include <fcntl.h>
00017 #include <string.h>
00018 #include <time.h>
00019 #include <stdio.h>
00020 #include <unistd.h>
00021 #include <utime.h>
00022 #include <sys/mman.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 
00026 #include "XrdFrm/XrdFrmAdmin.hh"
00027 #include "XrdFrm/XrdFrmConfig.hh"
00028 #include "XrdFrm/XrdFrmTrace.hh"
00029 #include "XrdOss/XrdOss.hh"
00030 #include "XrdOss/XrdOssOpaque.hh"
00031 #include "XrdOss/XrdOssPath.hh"
00032 #include "XrdOss/XrdOssSpace.hh"
00033 #include "XrdOuc/XrdOucEnv.hh"
00034 #include "XrdOuc/XrdOucName2Name.hh"
00035 #include "XrdOuc/XrdOucTList.hh"
00036 #include "XrdSys/XrdSysPlatform.hh"
00037 
00038 using namespace XrdFrm;
00039   
00040 /******************************************************************************/
00041 /*                                 R e l o c                                  */
00042 /******************************************************************************/
00043 
00044 int XrdFrmAdmin::Reloc(char *srcLfn, char *Space)
00045 {
00046    static const int crOpts = (O_CREAT|O_EXCL)<<8;
00047    class relocRecover
00048         {public:
00049          char *Lfn;
00050                relocRecover() : Lfn(0) {}
00051               ~relocRecover() {if (Lfn) Config.ossFS->Unlink(Lfn);}
00052          } Recover;
00053 
00054    XrdOucTList   *pP;
00055    XrdOucEnv      myEnv;
00056    struct stat    srcStat, lokStat;
00057    struct utimbuf tBuff;
00058    char trgLfn[1032], trgPfn[1032], trgSpace[XrdOssSpace::minSNbsz];
00059    char srcLnk[1032], srcPfn[1032], srcSpace[XrdOssSpace::minSNbsz];
00060    char lokPfn[1032], ASize[32], *fsTarget = 0;
00061    int  rc, srcLsz = 0;
00062 
00063 // Obtain the target space information, verify that it exists
00064 //
00065    if (!(pP = ParseSpace(Space, &fsTarget))) return 4;
00066    strcpy(trgSpace, Space);
00067    if (fsTarget) *(fsTarget-1) = ':';
00068 
00069 // Get the pfn for the incomming path
00070 //
00071    if (!Config.LocalPath(srcLfn, srcPfn, sizeof(srcPfn)-8))
00072       {finalRC = 4; return 0;}
00073 
00074 // Make sure the source file exists and get its attributes
00075 //
00076    if (   lstat(srcPfn, &srcStat)) {Emsg(errno, "stat ", srcLfn); return 0;}
00077    if ((srcStat.st_mode & S_IFMT) == S_IFLNK)
00078       {if (stat(srcPfn, &srcStat)) {Emsg(errno, "stat ", srcLfn); return 0;}
00079        if ((srcLsz = readlink(srcPfn, srcLnk, sizeof(srcLnk)-1) < 0))
00080           {Emsg(errno, "read link ", srcLfn); return 0;}
00081        srcLnk[srcLsz] = '\0';
00082       } else *srcLnk = 0;
00083    XrdOssPath::getCname(srcPfn, srcSpace);
00084 
00085 // Check this operation really makes sense
00086 //
00087    if (!strcmp(srcSpace, trgSpace)
00088    ||  (fsTarget && !strncmp(fsTarget, srcLnk, strlen(fsTarget))))
00089       {Emsg(srcLfn, " already in space ", Space); return 0;}
00090 
00091 // Get the current lock file time
00092 //
00093    strcpy(lokPfn, srcPfn); strcat(lokPfn, ".lock");
00094    if (stat(lokPfn, &lokStat)) *lokPfn = '\0';
00095 
00096 // Generate the target lfn and pfn
00097 //
00098    strcpy(trgLfn, srcLfn); strcat(trgLfn, ".anew");
00099    if (!Config.LocalPath(trgLfn, trgPfn, sizeof(trgPfn)))
00100       {finalRC = 4; return 0;}
00101 
00102 // Set environmental variables
00103 //
00104    sprintf(ASize,"%lld", static_cast<long long>(srcStat.st_size));
00105    myEnv.Put("oss.asize", ASize);
00106    myEnv.Put("oss.cgroup",Space);
00107 
00108 // Allocate a new file in the target space
00109 //
00110    rc = Config.ossFS->Create("admin",trgLfn,srcStat.st_mode&S_IAMB,myEnv,crOpts);
00111    if (rc) {Emsg(rc, "create placeholder for ", trgLfn); return 0;}
00112 
00113 // Now copy the source file to the target location. While we could possibly
00114 // have done a rename, this could have potentially disrupted access to the file.
00115 // Perform the reloc based on src/trg location
00116 //
00117    Recover.Lfn = trgPfn;
00118    if (!RelocCP(srcPfn, trgPfn, srcStat.st_size)) return 0;
00119 
00120 // Set the time of the file to it's original value
00121 //
00122    tBuff.actime = srcStat.st_atime;
00123    tBuff.modtime= srcStat.st_mtime;
00124    if (utime(trgPfn, &tBuff)) Emsg(errno, "set mtime for ", trgPfn);
00125 
00126 // Set the lock file time (do not let the reloc complete unless we can)
00127 //
00128    if (*lokPfn)
00129       {strcpy(lokPfn, trgPfn); strcat(lokPfn, ".lock");
00130        tBuff.actime = lokStat.st_atime;
00131        tBuff.modtime= lokStat.st_mtime;
00132        if (utime(lokPfn, &tBuff)) Emsg(errno, "set mtime for ", srcLfn);
00133        return 0;
00134       }
00135 
00136 // Rename the new file to the old file
00137 //
00138    if ((rc = Config.ossFS->Rename(trgLfn, srcLfn)))
00139       {Emsg(-rc, "rename ", trgPfn); return 0;}
00140    Recover.Lfn = 0;
00141 
00142 // Now adjust space as needed
00143 //
00144    XrdOssSpace::Adjust(trgSpace,  srcStat.st_size, XrdOssSpace::Pstg);
00145    XrdOssSpace::Adjust(srcSpace, -srcStat.st_size, XrdOssSpace::Purg);
00146 
00147 // If the source was another cache file syste, we need to remove the remnants
00148 //
00149    if (srcLsz)
00150       {if (symlink(srcLnk, trgPfn))
00151           {Emsg(errno, "create symlink to ", srcLnk); return 0;}
00152        if ((rc = Config.ossFS->Unlink(trgLfn)))
00153           {Emsg(errno, "remove ", trgPfn); return 0;}
00154       }
00155 
00156 // All done
00157 //
00158    Msg(srcLfn, " relocated from space ", srcSpace, " to ", Space);
00159    return 0;
00160 }
00161 
00162 /******************************************************************************/
00163 /*                               R e l o c C P                                */
00164 /******************************************************************************/
00165   
00166 int XrdFrmAdmin::RelocCP(const char *inFn, const char *outFn, off_t inSz)
00167 {
00168    static const size_t segSize = 1024*1024;
00169    class ioFD
00170         {public:
00171          int FD;
00172              ioFD() : FD(-1) {}
00173             ~ioFD() {if (FD >= 0) close(FD);}
00174         } In, Out;
00175 
00176    char *inBuff, ioBuff[segSize], *bP;
00177    off_t  inOff=0, Offset=0, Size=inSz, outSize=segSize, inSize=segSize;
00178    size_t ioSize;
00179    ssize_t rLen;
00180 
00181 // Open the input file
00182 //
00183    if ((In.FD = open(inFn, O_RDONLY)) < 0)
00184       {Emsg(errno, "open ", inFn); return 1;}
00185 
00186 // Open the output file
00187 //
00188    if ((Out.FD = open(outFn, O_WRONLY)) < 0)
00189       {Emsg(errno, "open ", outFn); return 1;}
00190 
00191 // We now copy 1MB segments using direct I/O
00192 //
00193    ioSize = (Size < (int)segSize ? Size : segSize);
00194    while(Size)
00195         {if ((inBuff = (char *)mmap(0, ioSize, PROT_READ,
00196                        MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
00197             {Emsg(errno, "memory map ", inFn); break;}
00198          if (!RelocWR(outFn, Out.FD, inBuff, ioSize, Offset)) break;
00199          Size -= ioSize; Offset += ioSize;
00200          if (munmap(inBuff, ioSize) < 0)
00201             {Emsg(errno, "unmap memory for ", inFn); break;}
00202          if (Size < (int)segSize) ioSize = Size;
00203         }
00204 
00205 // Return if all went well, otherwise check if we can recover
00206 //
00207    if (!Size || Size != inSz) return Size == 0;
00208    Msg("Trying traditional copy....");
00209 
00210 // Do a traditional copy
00211 //
00212    inSize = (inSz < (int)segSize ? Size : segSize);
00213    while(Size)
00214         {if (Size < (int)ioSize) outSize = inSize = Size;
00215          bP = ioBuff;
00216          while(inSize)
00217               {if ((rLen = pread(In.FD, bP, inSize, inOff)) < 0)
00218                   {if (errno == EINTR) continue;
00219                       else {Emsg(errno, "read ", inFn); return 0;}
00220                   }
00221                bP += rLen; inSize -= rLen; inOff += rLen;
00222               }
00223          if (!RelocWR(outFn, Out.FD, ioBuff, outSize, Offset)) return 0;
00224          Size -= outSize; Offset += outSize;
00225         }
00226 
00227 // Success
00228 //
00229    return 1;
00230 }
00231 
00232 /******************************************************************************/
00233   
00234 int XrdFrmAdmin::RelocWR(const char *outFn,
00235                          int oFD, char *Buff, size_t BLen, off_t BOff)
00236 {
00237    ssize_t wLen;
00238 
00239 // Copy out a segment
00240 //
00241    while(BLen)
00242         {if ((wLen = pwrite(oFD, Buff, BLen, BOff)) < 0)
00243             {if (errno == EINTR) continue;
00244                 else break;
00245             }
00246          Buff += wLen; BLen -= wLen; BOff += wLen;
00247         }
00248 
00249 // Check for errors
00250 //
00251    if (!BLen) return 1;
00252    Emsg(errno, "write ", outFn);
00253    return 0;
00254 }

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