39 #include <sys/types.h>
63 static const int crOpts = (O_CREAT|O_EXCL)<<8;
67 relocRecover() : Lfn(0) {}
73 struct stat srcStat, lokStat;
77 char lokPfn[1032], ASize[32], *fsTarget = 0;
82 if (!(pP = ParseSpace(Space, &fsTarget)))
return 4;
83 strcpy(trgSpace, Space);
84 if (fsTarget) *(fsTarget-1) =
':';
88 if (!
Config.LocalPath(srcLfn, srcPfn,
sizeof(srcPfn)-8))
89 {finalRC = 4;
return 0;}
93 if (
lstat(srcPfn, &srcStat)) {Emsg(errno,
"stat ", srcLfn);
return 0;}
94 if ((srcStat.st_mode & S_IFMT) == S_IFLNK)
95 {
if (
stat(srcPfn, &srcStat)) {Emsg(errno,
"stat ", srcLfn);
return 0;}
96 if ((srcLsz = readlink(srcPfn, srcLnk,
sizeof(srcLnk)-1) < 0))
97 {Emsg(errno,
"read link ", srcLfn);
return 0;}
98 srcLnk[srcLsz] =
'\0';
104 if (!strcmp(srcSpace, trgSpace)
105 || (fsTarget && !strncmp(fsTarget, srcLnk, strlen(fsTarget))))
106 {Emsg(srcLfn,
" already in space ", Space);
return 0;}
110 strcpy(lokPfn, srcPfn); strcat(lokPfn,
".lock");
111 if (
stat(lokPfn, &lokStat)) *lokPfn =
'\0';
115 strcpy(trgLfn, srcLfn); strcat(trgLfn,
".anew");
116 if (!
Config.LocalPath(trgLfn, trgPfn,
sizeof(trgPfn)))
117 {finalRC = 4;
return 0;}
121 sprintf(ASize,
"%lld",
static_cast<long long>(srcStat.st_size));
122 myEnv.
Put(
"oss.asize", ASize);
123 myEnv.
Put(
"oss.cgroup",Space);
128 if (rc) {Emsg(rc,
"create placeholder for ", trgLfn);
return 0;}
134 Recover.Lfn = trgPfn;
135 if (!RelocCP(srcPfn, trgPfn, srcStat.st_size))
return 0;
139 tBuff.actime = srcStat.st_atime;
140 tBuff.modtime= srcStat.st_mtime;
141 if (utime(trgPfn, &tBuff)) Emsg(errno,
"set mtime for ", trgPfn);
146 {strcpy(lokPfn, trgPfn); strcat(lokPfn,
".lock");
147 tBuff.actime = lokStat.st_atime;
148 tBuff.modtime= lokStat.st_mtime;
149 if (utime(lokPfn, &tBuff)) Emsg(errno,
"set mtime for ", srcLfn);
156 {Emsg(-rc,
"rename ", trgPfn);
return 0;}
167 {
if (symlink(srcLnk, trgPfn))
168 {Emsg(errno,
"create symlink to ", srcLnk);
return 0;}
170 {Emsg(errno,
"remove ", trgPfn);
return 0;}
175 Msg(srcLfn,
" relocated from space ", srcSpace,
" to ", Space);
183 int XrdFrmAdmin::RelocCP(
const char *inFn,
const char *outFn, off_t inSz)
185 static const size_t segSize = 1024*1024;
190 ~ioFD() {
if (FD >= 0)
close(FD);}
193 char *inBuff, ioBuff[segSize], *bP;
194 off_t inOff=0, Offset=0, Size=inSz, outSize=segSize, inSize=segSize;
200 if ((In.FD =
open(inFn, O_RDONLY)) < 0)
201 {Emsg(errno,
"open ", inFn);
return 1;}
205 if ((Out.FD =
open(outFn, O_WRONLY)) < 0)
206 {Emsg(errno,
"open ", outFn);
return 1;}
210 ioSize = (Size < (int)segSize ? Size : segSize);
212 {
if ((inBuff = (
char *)mmap(0, ioSize, PROT_READ,
213 MAP_NORESERVE|MAP_PRIVATE, In.FD, Offset)) == MAP_FAILED)
214 {Emsg(errno,
"memory map ", inFn);
break;}
215 if (!RelocWR(outFn, Out.FD, inBuff, ioSize, Offset))
break;
216 Size -= ioSize; Offset += ioSize;
217 if (munmap(inBuff, ioSize) < 0)
218 {Emsg(errno,
"unmap memory for ", inFn);
break;}
219 if (Size < (
int)segSize) ioSize = Size;
224 if (!Size || Size != inSz)
return Size == 0;
225 Msg(
"Trying traditional copy....");
229 inSize = (inSz < (int)segSize ? Size : segSize);
231 {
if (Size < (
int)ioSize) outSize = inSize = Size;
234 {
if ((rLen =
pread(In.FD, bP, inSize, inOff)) < 0)
235 {
if (errno == EINTR)
continue;
236 else {Emsg(errno,
"read ", inFn);
return 0;}
238 bP += rLen; inSize -= rLen; inOff += rLen;
240 if (!RelocWR(outFn, Out.FD, ioBuff, outSize, Offset))
return 0;
241 Size -= outSize; Offset += outSize;
251 int XrdFrmAdmin::RelocWR(
const char *outFn,
252 int oFD,
char *Buff,
size_t BLen, off_t BOff)
259 {
if ((wLen =
pwrite(oFD, Buff, BLen, BOff)) < 0)
260 {
if (errno == EINTR)
continue;
263 Buff += wLen; BLen -= wLen; BOff += wLen;
269 Emsg(errno,
"write ", outFn);
ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
int lstat(const char *path, struct stat *buf)
static int getCname(const char *path, char *Cache, char *lbuf=0, int lbsz=0)
static const int minSNbsz
static void Adjust(int Gent, off_t Space, sType=Serv)
virtual int Create(const char *tid, const char *path, mode_t mode, XrdOucEnv &env, int opts=0)=0
virtual int Rename(const char *oPath, const char *nPath, XrdOucEnv *oEnvP=0, XrdOucEnv *nEnvP=0)=0
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
void Put(const char *varname, const char *value)