XRootD
XrdOfsCPFile Class Reference

#include <XrdOfsCPFile.hh>

+ Collaboration diagram for XrdOfsCPFile:

Classes

class  rInfo
 

Public Member Functions

 XrdOfsCPFile (const char *cfn=0)
 
 ~XrdOfsCPFile ()
 Destructor. More...
 
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 }
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
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  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
Definition: XrdOfsCPFile.cc:61
int unlink(const char *path)
int fsync(int fildes)
#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 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().

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 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 }
int rename(const char *oldpath, const char *newpath)

References rename().

Referenced by Destroy().

+ Here is the call graph for this function:
+ 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().

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 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.

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

+ Here is the caller graph for this function:

◆ 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
Definition: XrdOfsCPFile.cc:52
ssize_t read(int fildes, void *buf, size_t nbyte)
#define fstat(a, b)
Definition: XrdPosix.hh:62
#define stat(a, b)
Definition: XrdPosix.hh:101
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 522 of file XrdOfsCPFile.cc.

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

References fsync().

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

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