XRootD
Loading...
Searching...
No Matches
XrdOfsCPFile Class Reference

#include <XrdOfsCPFile.hh>

+ Collaboration diagram for XrdOfsCPFile:

Classes

class  rInfo
 

Public Member Functions

 XrdOfsCPFile (const char *cfn=0)
 
 ~XrdOfsCPFile ()
 Destructor.
 
int Append (const char *data, off_t offset, int dlen)
 
int Create (const char *lfn, struct stat &Stat)
 
int Destroy ()
 
int ErrState ()
 
const char * FName (bool trim=false)
 
bool isActive ()
 
bool Reserve (int dlen, int nseg)
 
int RestoreInfo (rInfo &rinfo, const char *&ewhy)
 
int Sync ()
 
int Used (int nseg=0)
 

Static Public Member Functions

static char * Target (const char *ckpfn)
 

Detailed Description

Definition at line 39 of file XrdOfsCPFile.hh.

Constructor & Destructor Documentation

◆ XrdOfsCPFile()

XrdOfsCPFile::XrdOfsCPFile ( const char * cfn = 0)

Constructor

Parameters
cfn- Pointer to the name of the checkpoint file to use. When supplied, creates are prohibited.

Definition at line 136 of file XrdOfsCPFile.cc.

137 : ckpFN(ckpfn ? strdup(ckpfn) : 0), ckpFD(-1),
138 ckpDLen(0), ckpSize(0) {}

◆ ~XrdOfsCPFile()

XrdOfsCPFile::~XrdOfsCPFile ( )

Destructor.

Definition at line 144 of file XrdOfsCPFile.cc.

145{
146
147// Close the file descriptor if need be
148//
149 if (ckpFD >= 0) close(ckpFD);
150 if (ckpFN) free(ckpFN);
151}
#define close(a)
Definition XrdPosix.hh:48

References close.

Member Function Documentation

◆ Append()

int XrdOfsCPFile::Append ( const char * data,
off_t offset,
int dlen )

Append data to the checkpoint. Appends should be followed by Sync().

Parameters
data- Pointer to the data to be recorded.
offset- Offset in the source file where data came from.
dlen- Length of the data.
Returns
0 upon success and -errno upon failure.

Definition at line 157 of file XrdOfsCPFile.cc.

158{
159 struct iovec ioV[2];
160 cpSeg theSeg;
161 int retval;
162
163// Account for the data we will be writing
164//
165 ckpDLen += dlen;
166 ckpSize += dlen + segSZ;
167
168// Construct the next segment
169//
170 theSeg.dataOfs = offset;
171 theSeg.dataLen = dlen;
172
173// Compute checksum of the data and the segment information
174//
175 theSeg.crc32C = XrdOucCRC::Calc32C(((char *)&theSeg)+crcSZ, segSZ-crcSZ);
176 theSeg.crc32C = XrdOucCRC::Calc32C(data, dlen, theSeg.crc32C);
177
178// Construct iovec to write both pieces out
179//
180 ioV[0].iov_base = &theSeg;
181 ioV[0].iov_len = segSZ;
182 ioV[1].iov_base = (void *)data;
183 ioV[1].iov_len = dlen;
184
185// Write the data out
186//
187 retval = writev(ckpFD, ioV, 2);
188 if (retval != (int)(dlen+segSZ)) return (retval < 0 ? -errno : -EIO);
189
190// All done
191//
192 return 0;
193}
#define writev(a, b, c)
Definition XrdPosix.hh:117
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
Definition XrdOucCRC.cc:190

References XrdOucCRC::Calc32C(), and writev.

+ Here is the call graph for this function:

◆ Create()

int XrdOfsCPFile::Create ( const char * lfn,
struct stat & Stat )

Create a checkpoint

Parameters
lfn- Pointer to the name of the source file being checkpointed.
Stat- Reference to source file stat information.
Returns
0 upon success and -errno upon failure.

Definition at line 199 of file XrdOfsCPFile.cc.

200{
201 static const int oFlag = O_CREAT | O_EXCL | O_WRONLY;
202 static const int oMode = S_IRUSR | S_IWUSR | S_IRGRP;
203 struct iovec ioV[2];
204 cpHdr theHdr;
205 int retval, rc = 0;
206
207// Make sure we do not have an active checkpoint here
208//
209 if (ckpFD >= 0 || ckpFN) return -EEXIST;
210
211// Generate the path to the checkpoint file
212//
213 ckpFN = genCkpPath();
214 if (!ckpFN) return -ENOMEM;
215
216// Create the checkpoint file and set its attribute
217//
218 if ((ckpFD = XrdSysFD_Open(ckpFN, oFlag, oMode)) < 0
219 || XATTR.Set(attrName, srcFN, strlen(srcFN)+1, ckpFN, ckpFD) < 0)
220 {rc = -errno;
221 if (ckpFD >= 0) {close(ckpFD); ckpFD = -1;}
222 unlink(ckpFN);
223 free(ckpFN);
224 ckpFN = 0;
225 return rc;
226 }
227
228// Construct the header
229//
230 theHdr.lfnLen = strlen(srcFN) + 1;
231 theHdr.hdrLen = hdrSZ + theHdr.lfnLen;
232 theHdr.fSize = Stat.st_size;
233 theHdr.mTime = Stat.st_mtime;
234 memcpy(theHdr.srcUrl, " file://", sizeof(theHdr.srcUrl));
235 memset(theHdr.rsvd, 0, sizeof(theHdr.rsvd));
236
237// Generate CRC32C checksum for the header and source filename
238//
239 theHdr.crc32C = XrdOucCRC::Calc32C(((char *)&theHdr)+crcSZ, hdrSZ-crcSZ);
240 theHdr.crc32C = XrdOucCRC::Calc32C(srcFN, theHdr.lfnLen, theHdr.crc32C);
241
242// Construct I/O vector to write out the header
243//
244 ioV[0].iov_base = &theHdr;
245 ioV[0].iov_len = sizeof(theHdr);
246 ioV[1].iov_base = (void *)srcFN;
247 ioV[1].iov_len = theHdr.lfnLen;
248 ckpSize = sizeof(theHdr) + theHdr.lfnLen;
249
250// Write out the header and make sure it gets stored
251//
252 retval = writev(ckpFD, ioV, 2);
253 if (retval != ckpSize) rc = (retval < 0 ? -errno : -EIO);
254 else if (fsync(ckpFD)) rc = -errno;
255
256// Eliminate the checkpoint file if we encountered any error
257//
258 if (rc) {if (ftruncate(ckpFD, 0) && unlink(ckpFN)) {}}
259 return rc;
260}
struct stat Stat
Definition XrdCks.cc:49
#define XATTR
#define fsync(a)
Definition XrdPosix.hh:64
#define unlink(a)
Definition XrdPosix.hh:113
#define ftruncate(a, b)
Definition XrdPosix.hh:70

References XrdOucCRC::Calc32C(), close, fsync, ftruncate, Stat, stat, unlink, writev, and XATTR.

+ Here is the call graph for this function:

◆ Destroy()

int XrdOfsCPFile::Destroy ( )

Destroy a checkpoint

Returns
0 upon success and -errno upon failure.

Definition at line 266 of file XrdOfsCPFile.cc.

267{
268 int rc;
269
270// Attempt to destroy the checkpoint file
271//
272 if (ckpFN && unlink(ckpFN))
273 {rc = errno;
274 if (!truncate(ckpFN, 0) || !ErrState()) rc = 0;
275 } else rc = 0;
276
277// All done
278//
279 return rc;
280}
#define truncate(a, b)
Definition XrdPosix.hh:111

References ErrState(), truncate, and unlink.

+ Here is the call graph for this function:

◆ ErrState()

int XrdOfsCPFile::ErrState ( )

Place checkpoint file in error state.

Returns
0 upon success and -errno upon failure.

Definition at line 286 of file XrdOfsCPFile.cc.

287{
288 char buff[MAXPATHLEN+8];
289
290// Place checkpoint file in error state. If the rename fails, then the
291// checkpoint will be applied again which should fail anyway. This just
292// tries to avoid that issue and leave a trail.
293//
294 snprintf(buff, sizeof(buff), "%serr", ckpFN);
295 return (rename(ckpFN, buff) ? -errno : 0);
296}
#define rename(a, b)
Definition XrdPosix.hh:92

References rename.

Referenced by Destroy().

+ Here is the caller graph for this function:

◆ FName()

const char * XrdOfsCPFile::FName ( bool trim = false)

Get the checkpoint file name.

Returns
pointer to the checkpoint file name. The pointer will be "???" if there is no checkpoint file established.

Definition at line 302 of file XrdOfsCPFile.cc.

303{
304 if (ckpFN)
305 {if (trim)
306 {char *slash = rindex(ckpFN, '/');
307 if (slash) return slash+1;
308 }
309 return ckpFN;
310 }
311 return "???";
312}
void trim(std::string &str)
Definition XrdHttpReq.cc:77

References trim().

+ Here is the call graph for this function:

◆ isActive()

bool XrdOfsCPFile::isActive ( )
inline

Check if checpoint is established.

Returns
True if checkpoint has been established and false otherwise.

Definition at line 97 of file XrdOfsCPFile.hh.

97{return ckpFN != 0;}

◆ Reserve()

bool XrdOfsCPFile::Reserve ( int dlen,
int nseg )

Reserve space for a subsequent checkpoint.

Parameters
dlen- the number of bytes that will be writen.
nseg- the number of segements that will be written.
Returns
True upon success and false otherwise

Definition at line 355 of file XrdOfsCPFile.cc.

356{
357// Make sure paramenters are valid
358//
359 if (dlen < 0 || nseg < 0 || ckpFD < 0) return false;
360
361// Calculate the amount of space to reserve
362//
363 dlen += nseg*segSZ;
364
365// Now allocate the space
366//
367#ifdef __APPLE__
368 fstore_t Store = {F_ALLOCATEALL, F_PEOFPOSMODE, ckpSize, dlen, 0};
369 if (fcntl(ckpFD, F_PREALLOCATE, &Store) == -1
370 && ftruncate(ckpFD, ckpSize + dlen) == -1) return false;
371#else
372 if (posix_fallocate(ckpFD, ckpSize, dlen))
373 {if (ftruncate(ckpFD, ckpSize)) {}
374 return false;
375 }
376#endif
377
378// All done
379//
380 return true;
381}

References ftruncate.

◆ RestoreInfo()

int XrdOfsCPFile::RestoreInfo ( XrdOfsCPFile::rInfo & rinfo,
const char *& ewhy )

Definition at line 387 of file XrdOfsCPFile.cc.

388{
389 std::vector<XrdOucIOVec> vecIO;
390 struct stat Stat;
391 XrdOucIOVec *ioV, ioItem;
392 char *ckpRec, *ckpEnd;
393 cpSeg theSeg;
394 cUp cup;
395 int retval;
396 bool aOK;
397
398// Open the file
399//
400 if ((cup.fd = XrdSysFD_Open(ckpFN, O_RDONLY)) < 0)
401 {if (errno == ENOENT) return -ENOENT;
402 eWhy = "open failed";
403 return getSrcLfn(ckpFN, rinfo, cup.fd, errno);
404 }
405
406// Get the size of the file
407//
408 if (fstat(cup.fd, &Stat))
409 {eWhy = "stat failed";
410 return getSrcLfn(ckpFN, rinfo, cup.fd, errno);
411 }
412
413// If this is a zero length file, then it has not been comitted which is OK
414//
415 if (Stat.st_size == 0) return getSrcLfn(ckpFN, rinfo, cup.fd, ENODATA);
416
417// The file must be at least the basic record size
418//
419 if (Stat.st_size < hdrSZ+1)
420 {eWhy = "truncated header";
421 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
422 }
423
424// Allocate memory to read the whole file
425//
426 if (!(ckpRec = (char *)malloc(Stat.st_size)))
427 return getSrcLfn(ckpFN, rinfo, cup.fd, ENOMEM);
428 rinfo.rBuff = ckpRec;
429
430// Now read the whole file into the buffer
431//
432 if ((retval = read(cup.fd, ckpRec, Stat.st_size)) != Stat.st_size)
433 {eWhy = "read failed";
434 return getSrcLfn(ckpFN, rinfo, cup.fd, (retval < 0 ? errno : EIO));
435 }
436
437// We have a catch-22 as we need to use the record length to verify the checksum
438// but it may have been corrupted. So, we first verify the value is reasonably
439// correct relative to the value of the lfn length and the fixed header length.
440//
441 cpHdr &theHdr = *((cpHdr *)ckpRec);
442 if (theHdr.hdrLen > Stat.st_size
443 || (theHdr.hdrLen - theHdr.lfnLen) != (int)hdrSZ)
444 {eWhy = "corrupted header";
445 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
446 }
447
448// Verify the header checksum
449//
450 if (!XrdOucCRC::Ver32C(ckpRec+crcSZ, theHdr.hdrLen-crcSZ, theHdr.crc32C))
451 {eWhy = "header checksum mismatch";
452 return getSrcLfn(ckpFN, rinfo, cup.fd, EDOM);
453 }
454
455// Set the source file name and other information
456//
457 rinfo.srcLFN = ckpRec+hdrSZ;
458 rinfo.fSize = theHdr.fSize;
459 rinfo.mTime = theHdr.mTime;
460
461// Prepare to verify and record the segments
462//
463 ckpEnd = ckpRec + Stat.st_size;
464 ckpRec = ckpRec + theHdr.hdrLen;
465 ioItem.info = 0;
466 vecIO.reserve(16);
467
468// Verify all of the segments
469//
470 aOK = false; eWhy = 0;
471 while(ckpRec+sizeof(cpSeg) < ckpEnd)
472 {memcpy(&theSeg, ckpRec, segSZ);
473 if (!theSeg.dataLen && !theSeg.dataOfs && !theSeg.crc32C)
474 {aOK = true;
475 break;
476 }
477 char *ckpData = ckpRec + segSZ;
478 if (theSeg.dataLen <= 0 || ckpData + theSeg.dataLen > ckpEnd) break;
479 int cLen = theSeg.dataLen+sizeof(cpSeg)-crcSZ;
480 if (!XrdOucCRC::Ver32C(ckpRec+crcSZ, cLen, theSeg.crc32C))
481 {eWhy = "data checksum mismatch";
482 break;
483 }
484 ioItem.offset = theSeg.dataOfs;
485 ioItem.size = theSeg.dataLen;
486 ioItem.data = ckpRec + segSZ;
487 rinfo.DataLen += theSeg.dataLen;
488 vecIO.push_back(ioItem);
489 ckpRec += (segSZ + theSeg.dataLen);
490 }
491
492// Check that we ended perfectly (we accept a failed write as long as the
493// space was already allocated).
494//
495 if (!aOK && ckpRec != ckpEnd)
496 {if (!eWhy) eWhy = "truncated file";
497 return -EDOM;
498 }
499
500// If the file had no data changed, return as only the size changed. Otherwise,
501// allocate an iovec for all of the segments we need to restore.
502//
503 if (!vecIO.size()) return 0;
504 ioV = new XrdOucIOVec[vecIO.size()];
505
506// Fill in the vector in reverse order as this is the restore sequence
507//
508 int j = vecIO.size() - 1;
509 for (int i = 0; i < (int)vecIO.size(); i++) ioV[j--] = vecIO[i];
510
511// All done
512//
513 rinfo.DataVec = ioV;
514 rinfo.DataNum = vecIO.size();
515 return 0;
516}
#define ENODATA
#define fstat(a, b)
Definition XrdPosix.hh:62
#define stat(a, b)
Definition XrdPosix.hh:101
#define read(a, b, c)
Definition XrdPosix.hh:82
int64_t fSize
Original size of the source file.
const char * srcLFN
Pointer to the source filename.
XrdOucIOVec * DataVec
A vector of data that must be written back.
int DataLen
Number of bytes to write back (may be 0)
int DataNum
Number of elements in DataVec (may be 0)
time_t mTime
Original modification time of the source.
static bool Ver32C(const void *data, size_t count, const uint32_t csval, uint32_t *csbad=0)
Definition XrdOucCRC.cc:222

References XrdOfsCPFile::rInfo::DataLen, XrdOfsCPFile::rInfo::DataNum, XrdOfsCPFile::rInfo::DataVec, ENODATA, XrdOfsCPFile::rInfo::fSize, fstat, XrdOfsCPFile::rInfo::mTime, read, XrdOfsCPFile::rInfo::srcLFN, Stat, stat, and XrdOucCRC::Ver32C().

+ Here is the call graph for this function:

◆ Sync()

int XrdOfsCPFile::Sync ( )

Commit data to media.

Returns
0 upon success and -errno upon failure.

Definition at line 522 of file XrdOfsCPFile.cc.

523{
524 if (fsync(ckpFD)) return -errno;
525 return 0;
526}

References fsync.

◆ Target()

char * XrdOfsCPFile::Target ( const char * ckpfn)
static

Get the name of the source file associated with a checkpoint file.

Parameters
ckpfn- Pointer to the name of the checkpoint file to use.
Returns
pointer to either the source file name or reason it's not valid.

Definition at line 532 of file XrdOfsCPFile.cc.

533{
534 struct {cpHdr hdr; char srcfn[MAXPATHLEN+8];} ckpRec;
535 cUp cup;
536 const char *eMsg = "Target unknown; corrupt checkpoint file";
537 int n;
538
539// Try to get the name via the extended attributes first
540//
541 if ((n = XATTR.Get(attrName,ckpRec.srcfn,sizeof(ckpRec.srcfn)-1,ckpfn)) > 0)
542 {ckpRec.srcfn[n] = 0;
543 return strdup(ckpRec.srcfn);
544 }
545
546// Open the file
547//
548 if ((cup.fd = XrdSysFD_Open(ckpfn, O_RDONLY)) < 0)
549 {char buff[256];
550 snprintf(buff, sizeof(buff), "Target unknown; %s", XrdSysE2T(errno));
551 return strdup(buff);
552 }
553
554// Now read the file header
555//
556 if ((n = read(cup.fd, &ckpRec, sizeof(ckpRec))) <= (int)sizeof(cpHdr))
557 return strdup(eMsg);
558
559// Make sure the length of the lfn is reasonable
560//
561 if (ckpRec.hdr.lfnLen <= 1 || ckpRec.hdr.lfnLen > (int)MAXPATHLEN)
562 return strdup(eMsg);
563
564// Return a copy of the filename
565//
566 ckpRec.srcfn[ckpRec.hdr.lfnLen-1] = 0;
567 return strdup(ckpRec.srcfn);
568}
#define eMsg(x)
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104

References eMsg, read, XATTR, and XrdSysE2T().

+ Here is the call graph for this function:

◆ Used()

int XrdOfsCPFile::Used ( int nseg = 0)

Get the curent size of the checkpoint file.

Parameters
nseg- the number of future segments to account for.
Returns
The size of the file in bytes.

Definition at line 574 of file XrdOfsCPFile.cc.

574{return ckpSize + (nseg*segSZ);}

The documentation for this class was generated from the following files: