00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
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
00064
00065 if (!(pP = ParseSpace(Space, &fsTarget))) return 4;
00066 strcpy(trgSpace, Space);
00067 if (fsTarget) *(fsTarget-1) = ':';
00068
00069
00070
00071 if (!Config.LocalPath(srcLfn, srcPfn, sizeof(srcPfn)-8))
00072 {finalRC = 4; return 0;}
00073
00074
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
00086
00087 if (!strcmp(srcSpace, trgSpace)
00088 || (fsTarget && !strncmp(fsTarget, srcLnk, strlen(fsTarget))))
00089 {Emsg(srcLfn, " already in space ", Space); return 0;}
00090
00091
00092
00093 strcpy(lokPfn, srcPfn); strcat(lokPfn, ".lock");
00094 if (stat(lokPfn, &lokStat)) *lokPfn = '\0';
00095
00096
00097
00098 strcpy(trgLfn, srcLfn); strcat(trgLfn, ".anew");
00099 if (!Config.LocalPath(trgLfn, trgPfn, sizeof(trgPfn)))
00100 {finalRC = 4; return 0;}
00101
00102
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
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
00114
00115
00116
00117 Recover.Lfn = trgPfn;
00118 if (!RelocCP(srcPfn, trgPfn, srcStat.st_size)) return 0;
00119
00120
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
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
00137
00138 if ((rc = Config.ossFS->Rename(trgLfn, srcLfn)))
00139 {Emsg(-rc, "rename ", trgPfn); return 0;}
00140 Recover.Lfn = 0;
00141
00142
00143
00144 XrdOssSpace::Adjust(trgSpace, srcStat.st_size, XrdOssSpace::Pstg);
00145 XrdOssSpace::Adjust(srcSpace, -srcStat.st_size, XrdOssSpace::Purg);
00146
00147
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
00157
00158 Msg(srcLfn, " relocated from space ", srcSpace, " to ", Space);
00159 return 0;
00160 }
00161
00162
00163
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
00182
00183 if ((In.FD = open(inFn, O_RDONLY)) < 0)
00184 {Emsg(errno, "open ", inFn); return 1;}
00185
00186
00187
00188 if ((Out.FD = open(outFn, O_WRONLY)) < 0)
00189 {Emsg(errno, "open ", outFn); return 1;}
00190
00191
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
00206
00207 if (!Size || Size != inSz) return Size == 0;
00208 Msg("Trying traditional copy....");
00209
00210
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
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
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
00250
00251 if (!BLen) return 1;
00252 Emsg(errno, "write ", outFn);
00253 return 0;
00254 }