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.

Referenced by XrdOfsChkPnt::Truncate(), and XrdOfsChkPnt::Write().

+ Here is the call graph for this function:
+ Here is the caller 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
215// Create the checkpoint file and set its attribute
216//
217 if ((ckpFD = XrdSysFD_Open(ckpFN, oFlag, oMode)) < 0
218 || XATTR.Set(attrName, srcFN, strlen(srcFN)+1, ckpFN, ckpFD) < 0)
219 {rc = -errno;
220 if (ckpFD >= 0) {close(ckpFD); ckpFD = -1;}
221 unlink(ckpFN);
222 free(ckpFN);
223 ckpFN = 0;
224 }
225
226// Construct the header
227//
228 theHdr.lfnLen = strlen(srcFN) + 1;
229 theHdr.hdrLen = hdrSZ + theHdr.lfnLen;
230 theHdr.fSize = Stat.st_size;
231 theHdr.mTime = Stat.st_mtime;
232 memcpy(theHdr.srcUrl, " file://", sizeof(theHdr.srcUrl));
233 memset(theHdr.rsvd, 0, sizeof(theHdr.rsvd));
234
235// Generate CRC32C checksum for the header and source filename
236//
237 theHdr.crc32C = XrdOucCRC::Calc32C(((char *)&theHdr)+crcSZ, hdrSZ-crcSZ);
238 theHdr.crc32C = XrdOucCRC::Calc32C(srcFN, theHdr.lfnLen, theHdr.crc32C);
239
240// Construct I/O vector to write out the header
241//
242 ioV[0].iov_base = &theHdr;
243 ioV[0].iov_len = sizeof(theHdr);
244 ioV[1].iov_base = (void *)srcFN;
245 ioV[1].iov_len = theHdr.lfnLen;
246 ckpSize = sizeof(theHdr) + theHdr.lfnLen;
247
248// Write out the header and make sure it gets stored
249//
250 retval = writev(ckpFD, ioV, 2);
251 if (retval != ckpSize) rc = (retval < 0 ? -errno : -EIO);
252 else if (fsync(ckpFD)) rc = -errno;
253
254// Eliminate the checkpoint file if we encountered any error
255//
256 if (rc) {if (ftruncate(ckpFD, 0) && unlink(ckpFN)) {}}
257 return rc;
258}
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, unlink, writev, and XATTR.

Referenced by XrdOfsChkPnt::Create().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Destroy()

int XrdOfsCPFile::Destroy ( )

Destroy a checkpoint

Returns
0 upon success and -errno upon failure.

Definition at line 264 of file XrdOfsCPFile.cc.

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

References ErrState(), truncate, and unlink.

Referenced by XrdOfsChkPnt::Delete().

+ Here is the call graph for this function:
+ Here is the caller 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 284 of file XrdOfsCPFile.cc.

285{
286 char buff[MAXPATHLEN+8];
287
288// Place checkpoint file in error state. If the rename fails, then the
289// checkpoint will be applied again which should fail anyway. This just
290// tries to avoid that issue and leave a trail.
291//
292 snprintf(buff, sizeof(buff), "%serr", ckpFN);
293 return (rename(ckpFN, buff) ? -errno : 0);
294}
#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 300 of file XrdOfsCPFile.cc.

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

References trim().

Referenced by XrdOfsChkPnt::Create(), XrdOfsChkPnt::Delete(), and XrdOfsChkPnt::Restore().

+ Here is the call graph for this function:
+ Here is the caller 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;}

Referenced by XrdOfsChkPnt::Create(), XrdOfsChkPnt::Delete(), XrdOfsChkPnt::Restore(), XrdOfsChkPnt::Truncate(), and XrdOfsChkPnt::Write().

+ Here is the caller graph for this function:

◆ 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 353 of file XrdOfsCPFile.cc.

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

References fcntl(), and ftruncate.

Referenced by XrdOfsChkPnt::Truncate(), and XrdOfsChkPnt::Write().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ RestoreInfo()

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

Definition at line 385 of file XrdOfsCPFile.cc.

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

Referenced by XrdOfsChkPnt::Restore().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Sync()

int XrdOfsCPFile::Sync ( )

Commit data to media.

Returns
0 upon success and -errno upon failure.

Definition at line 520 of file XrdOfsCPFile.cc.

521{
522 if (fsync(ckpFD)) return -errno;
523 return 0;
524}

References fsync.

Referenced by XrdOfsChkPnt::Truncate(), and XrdOfsChkPnt::Write().

+ Here is the caller graph for this function:

◆ 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 530 of file XrdOfsCPFile.cc.

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

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

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