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:43

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 
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
Definition: XrdOfsCPFile.cc:61
int ftruncate(int fildes, off_t offset)
int unlink(const char *path)
int fsync(int fildes)

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 }
int truncate(const char *path, off_t offset)

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 }
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 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
Definition: XrdOfsCPFile.cc:52
int stat(const char *path, struct stat *buf)
int fstat(int fildes, struct stat *buf)
ssize_t read(int fildes, void *buf, size_t nbyte)
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 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 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: