XrdOssCopy.cc

Go to the documentation of this file.
00001 /******************************************************************************/
00002 /*                                                                            */
00003 /*                         X r d O s s C o p y . c c                          */
00004 /*                                                                            */
00005 /* (c) 2009 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: XrdOssCopy.cc 30949 2009-11-02 16:37:58Z ganis $
00012  
00013 const char *XrdOssCopyCVSID = "$Id: XrdOssCopy.cc 30949 2009-11-02 16:37:58Z 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 "XrdOss/XrdOssCopy.hh"
00027 #include "XrdOss/XrdOssTrace.hh"
00028 #include "XrdSys/XrdSysError.hh"
00029 
00030 /******************************************************************************/
00031 /*                  E r r o r   R o u t i n g   O b j e c t                   */
00032 /******************************************************************************/
00033   
00034 extern XrdSysError OssEroute;
00035 
00036 extern XrdOucTrace OssTrace;
00037 
00038 /******************************************************************************/
00039 /* Public:                          C o p y                                   */
00040 /******************************************************************************/
00041   
00042 off_t XrdOssCopy::Copy(const char *inFn, const char *outFn, int outFD)
00043 {
00044    static const size_t segSize = 1024*1024;
00045    class ioFD
00046         {public:
00047          int FD;
00048              ioFD(int fd=-1) : FD(fd) {}
00049             ~ioFD() {if (FD >= 0) close(FD);}
00050         } In, Out(outFD);
00051 
00052    struct utimbuf tBuff;
00053    struct stat buf;
00054    char *inBuff, *bP;
00055    off_t  Offset=0, fileSize;
00056    size_t ioSize, copySize;
00057    ssize_t rLen;
00058 
00059 // Open the input file
00060 //
00061    if ((In.FD = open(inFn, O_RDONLY)) < 0)
00062       {OssEroute.Emsg("Copy", errno, "open", inFn); return -1;}
00063 
00064 // Get the input filesize
00065 //
00066    if (fstat(In.FD, &buf))
00067       {OssEroute.Emsg("Copy", errno, "stat", outFn); return -1;}
00068    copySize = fileSize = buf.st_size;
00069 
00070 // We now copy 1MB segments using direct I/O
00071 //
00072    ioSize = (fileSize < (off_t)segSize ? fileSize : segSize);
00073    while(copySize)
00074         {if ((inBuff = (char *)mmap(0, ioSize, PROT_READ, 
00075                        MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
00076             {OssEroute.Emsg("Copy", errno, "memory map", inFn); break;}
00077          if (!Write(outFn, Out.FD, inBuff, ioSize, Offset)) break;
00078          copySize -= ioSize; Offset += ioSize;
00079          if (munmap(inBuff, ioSize) < 0)
00080             {OssEroute.Emsg("Copy", errno, "unmap memory for", inFn); break;}
00081          if (copySize < segSize) ioSize = copySize;
00082         }
00083 
00084 // Return if all went well, otherwise check if we can recover
00085 //
00086    if (!copySize)            return fileSize;
00087    if ((off_t)copySize != fileSize) return -1;
00088    OssEroute.Emsg("Copy", "Trying traditional copy for", inFn, "...");
00089 
00090 // Do a traditional copy (note that we didn't copy anything yet)
00091 //
00092   {char ioBuff[segSize];
00093    off_t rdSize, wrSize = segSize, inOff=0;
00094    while(copySize)
00095         {if (copySize < segSize) rdSize = wrSize = copySize;
00096             else rdSize = segSize;
00097          bP = ioBuff;
00098          while(rdSize)
00099               {do {rLen = pread(In.FD, bP, rdSize, inOff);}
00100                   while(rLen < 0 && errno == EINTR);
00101                if (rLen <= 0)
00102                   {OssEroute.Emsg("Copy",rLen ? errno : ECANCELED,"read",inFn);
00103                    return -1;
00104                   }
00105                bP += rLen; rdSize -= rLen; inOff += rLen;
00106               }
00107          if (!Write(outFn, Out.FD, ioBuff, wrSize, Offset)) return -1;
00108          copySize -= wrSize; Offset += wrSize;
00109         }
00110    }
00111 
00112 // Now set the time on the file to the original time
00113 //
00114    tBuff.actime = buf.st_atime;
00115    tBuff.modtime= buf.st_mtime;
00116    if (utime(outFn, &tBuff)) 
00117       OssEroute.Emsg("Copy", errno, "set mtime for", outFn);
00118 
00119 // Success
00120 //
00121    return fileSize;
00122 }
00123 
00124 /******************************************************************************/
00125 /* private:                        W r i t e                                  */
00126 /******************************************************************************/
00127   
00128 int XrdOssCopy::Write(const char *outFn,
00129                       int oFD, char *Buff, size_t BLen, off_t BOff)
00130 {
00131    ssize_t wLen;
00132 
00133 // Copy out a segment
00134 //
00135    while(BLen)
00136         {if ((wLen = pwrite(oFD, Buff, BLen, BOff)) < 0)
00137             {if (errno == EINTR) continue;
00138                 else break;
00139             }
00140          Buff += wLen; BLen -= wLen; BOff += wLen;
00141         }
00142 
00143 // Check for errors
00144 //
00145    if (!BLen) return 1;
00146    OssEroute.Emsg("Copy", errno, "write", outFn);
00147    return 0;
00148 }

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