XRootD
XrdSutPFile Class Reference

#include <XrdSutPFile.hh>

+ Collaboration diagram for XrdSutPFile:

Public Member Functions

 XrdSutPFile (const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
 
 XrdSutPFile (const XrdSutPFile &f)
 
virtual ~XrdSutPFile ()
 
kXR_int32 Browse (void *out=0)
 
kXR_int32 Close (kXR_int32 d=-1)
 
bool Init (const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
 
bool IsValid () const
 
kXR_int32 LastError () const
 
const char * LastErrStr () const
 
const char * Name () const
 
kXR_int32 Open (kXR_int32 opt, bool *wasopen=0, const char *nam=0, kXR_int32 createmode=0600)
 
kXR_int32 ReadCount (const char *nm, int &cnt)
 
kXR_int32 ReadEntry (const char *name, XrdSutPFEntry &ent, int opt=0)
 
kXR_int32 ReadEntry (kXR_int32 ofs, XrdSutPFEntry &ent)
 
kXR_int32 RemoveEntries (const char *name, char opt)
 
kXR_int32 RemoveEntry (const char *name)
 
kXR_int32 RemoveEntry (kXR_int32 ofs)
 
kXR_int32 ResetCount (const char *nm)
 
kXR_int32 RetrieveHeader (XrdSutPFHeader &hd)
 
kXR_int32 SearchEntries (const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
 
kXR_int32 SearchSpecialEntries (kXR_int32 *ofs=0, kXR_int32 nofs=1)
 
kXR_int32 Trim (const char *fbak=0)
 
kXR_int32 UpdateCount (const char *nm, int *cnt=0, int step=1, bool reset=0)
 
kXR_int32 UpdateHeader (XrdSutPFHeader hd)
 
kXR_int32 WriteEntry (XrdSutPFEntry ent)
 

Friends

class XrdSutPFCache
 

Detailed Description

Definition at line 121 of file XrdSutPFile.hh.

Constructor & Destructor Documentation

◆ XrdSutPFile() [1/2]

XrdSutPFile::XrdSutPFile ( const char *  n,
kXR_int32  openmode = kPFEcreate,
kXR_int32  createmode = 0600,
bool  hashtab = 1 
)

Definition at line 187 of file XrdSutPFile.cc.

189 {
190  // Constructor
191 
192  name = 0;
193  if (n) {
194  name = new char[strlen(n)+1];
195  if (name)
196  strcpy(name,n);
197  }
198  valid = 0;
199  fFd = -1;
200  fHTutime = -1;
201  fHashTable = 0;
202 
203  valid = Init(n, openmode, createmode, hashtab);
204 }
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
Definition: XrdSutPFile.cc:236

References Init().

+ Here is the call graph for this function:

◆ XrdSutPFile() [2/2]

XrdSutPFile::XrdSutPFile ( const XrdSutPFile f)

Definition at line 207 of file XrdSutPFile.cc.

208 {
209  // Copy constructor
210 
211  name = 0;
212  if (f.name) {
213  name = new char[strlen(f.name)+1];
214  if (name)
215  strcpy(name,f.name);
216  }
217  fFd = f.fFd ;
218 }

◆ ~XrdSutPFile()

XrdSutPFile::~XrdSutPFile ( )
virtual

Definition at line 221 of file XrdSutPFile.cc.

222 {
223  // Destructor
224 
225  if (name)
226  delete[] name;
227  name = 0;
228  if (fHashTable)
229  delete fHashTable;
230  fHashTable = 0;
231 
232  Close();
233 }
kXR_int32 Close(kXR_int32 d=-1)
Definition: XrdSutPFile.cc:450

References Close().

+ Here is the call graph for this function:

Member Function Documentation

◆ Browse()

kXR_int32 XrdSutPFile::Browse ( void *  out = 0)

Definition at line 1624 of file XrdSutPFile.cc.

1625 {
1626  // Display the content of the file
1627 
1628  // Make sure we got an open stream
1629  if (Open(1) < 0)
1630  return -1;
1631 
1632  // Read header
1633  XrdSutPFHeader hdr;
1634  if (ReadHeader(hdr) < 0) {
1635  Close();
1636  return -1;
1637  }
1638 
1639  // Time strings
1640  struct tm tst;
1641  char sctime[256] = {0};
1642  time_t ttmp = hdr.ctime;
1643  localtime_r(&ttmp,&tst);
1644  asctime_r(&tst,sctime);
1645  sctime[strlen(sctime)-1] = 0;
1646  char sitime[256] = {0};
1647  ttmp = hdr.itime;
1648  localtime_r(&ttmp,&tst);
1649  asctime_r(&tst,sitime);
1650  sitime[strlen(sitime)-1] = 0;
1651 
1652  // Default is stdout
1653  FILE *out = oout ? (FILE *)oout : stdout;
1654 
1655  fprintf(out,"//-----------------------------------------------------"
1656  "--------------------//\n");
1657  fprintf(out,"//\n");
1658  fprintf(out,"// File: %s\n",name);
1659  fprintf(out,"// ID: %s\n",hdr.fileID);
1660  fprintf(out,"// Version: %d\n",hdr.version);
1661  fprintf(out,"// Last change : %s (%d sec)\n",sctime,hdr.ctime);
1662  fprintf(out,"// Index change: %s (%d sec)\n",sitime,hdr.itime);
1663  fprintf(out,"//\n");
1664  fprintf(out,"// Number of Entries: %d\n",hdr.entries);
1665  fprintf(out,"// Bytes unreachable: %d\n",hdr.jnksiz);
1666  fprintf(out,"//\n");
1667 
1668  if (hdr.entries > 0) {
1669 
1670  // Special entries first, if any
1672  if (ns > 0) {
1673  // Allocate space for offsets
1674  kXR_int32 *sofs = new kXR_int32[ns];
1675  if (sofs) {
1676  // Get offsets
1677  ns = SearchSpecialEntries(sofs,ns);
1678  fprintf(out,"// Special entries (%d):\n",ns);
1679  int i = 0;
1680  for (; i<ns; i++) {
1681 
1682  // Read entry index at ofs
1683  XrdSutPFEntInd ind;
1684  if (ReadInd(sofs[i], ind) < 0) {
1685  Close();
1686  return -1;
1687  }
1688 
1689  if (ind.entofs) {
1690  // Read entry
1691  XrdSutPFEntry ent;
1692  if (ReadEnt(ind.entofs, ent) < 0) {
1693  Close();
1694  return -1;
1695  }
1696  char smt[20] = {0};
1697  XrdSutTimeString(ent.mtime,smt);
1698  std::string buffer;
1699  char buf[2048] = {0};
1700  memset(buf,0,2048);
1701  sprintf(buf,"// #%d mod:%s",i+1,smt);
1702  buffer = buf;
1703  sprintf(buf," name:%s",ind.name);
1704  buffer += buf;
1705  fprintf(out,"%s\n",buffer.c_str());
1706 
1707  buffer.clear();
1708  sprintf(buf,"// buf");
1709  buffer = buf;
1710 
1711  if (ent.cnt == 1) {
1712  if (ent.buf1.len && ent.buf1.buf)
1713  {
1714  sprintf(buf,": %.*s",ent.buf1.len,ent.buf1.buf);
1715  buffer += buf;
1716  }
1717  if (ent.buf2.len && ent.buf2.buf)
1718  {
1719  sprintf(buf,": %.*s",ent.buf2.len,ent.buf2.buf);
1720  buffer += buf;
1721  }
1722  if (ent.buf3.len && ent.buf3.buf)
1723  {
1724  sprintf(buf,": %.*s",ent.buf3.len,ent.buf3.buf);
1725  buffer += buf;
1726  }
1727  if (ent.buf4.len && ent.buf4.buf)
1728  {
1729  sprintf(buf,": %.*s",ent.buf4.len,ent.buf4.buf);
1730  buffer += buf;
1731  }
1732  } else {
1733  sprintf(buf,":%d:%d:%d:%d",
1734  ent.buf1.len,ent.buf2.len,ent.buf3.len,
1735  ent.buf4.len);
1736  buffer += buf;
1737  buffer += " (protected)";
1738  }
1739  fprintf(out,"%s\n",buf);
1740  }
1741  }
1742  fprintf(out,"//\n");
1743  delete[] sofs;
1744  }
1745  }
1746 
1747  if (hdr.entries > ns)
1748  fprintf(out,"// Normal entries (%d):\n",hdr.entries-ns);
1749 
1750  kXR_int32 nn = 0;
1751  kXR_int32 nxtofs = hdr.indofs;
1752  while (nxtofs) {
1753 
1754  // Read entry index at ofs
1755  XrdSutPFEntInd ind;
1756  if (ReadInd(nxtofs, ind) < 0) {
1757  Close();
1758  return -3;
1759  }
1760 
1761  if (ind.entofs) {
1762  // Read entry
1763  XrdSutPFEntry ent;
1764  if (ReadEnt(ind.entofs, ent) < 0) {
1765  Close();
1766  return -4;
1767  }
1768  if (ent.status != kPFE_special) {
1769  char smt[20] = {0};
1770  XrdSutTimeString(ent.mtime,smt);
1771 
1772  nn++;
1773  fprintf(out,
1774  "// #:%d st:%d cn:%d buf:%d,%d,%d,%d mod:%s name:%s\n",
1775  nn,ent.status,ent.cnt,ent.buf1.len,ent.buf2.len,ent.buf3.len,
1776  ent.buf4.len,smt,ind.name);
1777  }
1778  }
1779 
1780  // Read next
1781  nxtofs = ind.nxtofs;
1782  }
1783  fprintf(out,"//\n");
1784  }
1785  fprintf(out,"//-----------------------------------------------------"
1786  "--------------------//\n");
1787 
1788  // Close the file
1789  Close();
1790 
1791  return 0;
1792 }
int kXR_int32
Definition: XPtypes.hh:89
int XrdSutTimeString(int t, char *st, int opt)
Definition: XrdSutAux.cc:311
@ kPFE_special
kXR_int32 len
kXR_int32 entofs
Definition: XrdSutPFile.hh:88
kXR_int32 nxtofs
Definition: XrdSutPFile.hh:87
kXR_int32 mtime
XrdSutPFBuf buf3
XrdSutPFBuf buf1
XrdSutPFBuf buf2
XrdSutPFBuf buf4
kXR_int32 itime
Definition: XrdSutPFile.hh:107
kXR_int32 entries
Definition: XrdSutPFile.hh:108
kXR_int32 version
Definition: XrdSutPFile.hh:105
kXR_int32 ctime
Definition: XrdSutPFile.hh:106
kXR_int32 jnksiz
Definition: XrdSutPFile.hh:110
kXR_int32 indofs
Definition: XrdSutPFile.hh:109
char fileID[kFileIDSize]
Definition: XrdSutPFile.hh:104
kXR_int32 SearchSpecialEntries(kXR_int32 *ofs=0, kXR_int32 nofs=1)
kXR_int32 Open(kXR_int32 opt, bool *wasopen=0, const char *nam=0, kXR_int32 createmode=0600)
Definition: XrdSutPFile.cc:300

References XrdSutPFBuf::buf, XrdSutPFEntry::buf1, XrdSutPFEntry::buf2, XrdSutPFEntry::buf3, XrdSutPFEntry::buf4, Close(), XrdSutPFEntry::cnt, XrdSutPFHeader::ctime, XrdSutPFEntInd::entofs, XrdSutPFHeader::entries, XrdSutPFHeader::fileID, XrdSutPFHeader::indofs, XrdSutPFHeader::itime, XrdSutPFHeader::jnksiz, kPFE_special, XrdSutPFBuf::len, XrdSutPFEntry::mtime, XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, Open(), SearchSpecialEntries(), XrdSutPFEntry::status, XrdSutPFHeader::version, and XrdSutTimeString().

Referenced by main().

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

◆ Close()

kXR_int32 XrdSutPFile::Close ( kXR_int32  d = -1)

Definition at line 450 of file XrdSutPFile.cc.

451 {
452  // Close the open stream or descriptor fd, if > -1 .
453  // The file is unlocked before.
454 
455  // If not open, do nothing
456  if (fd < 0)
457  fd = fFd;
458  if (fd < 0)
459  return 0;
460 
461  //
462  // Unlock the file
463  struct flock flck;
464  memset(&flck, 0, sizeof(flck));
465  flck.l_type = F_UNLCK;
466  flck.l_whence = SEEK_SET;
467  if (fcntl(fd, F_SETLK, &flck) == -1) {
468  close(fd);
469  return Err(kPFErrUnlocking,"Close",(const char *)&fd);
470  }
471 
472  //
473  // Close it
474  close(fd);
475 
476  // Reset file descriptor
477  if (fd == fFd)
478  fFd = -1;
479 
480  return 0;
481 }
#define Err(p, a, b, c)
Definition: XrdNetSocket.cc:81
int fcntl(int fd, int cmd,...)
#define close(a)
Definition: XrdPosix.hh:43
@ kPFErrUnlocking
Definition: XrdSutPFile.hh:73

References close, Err, fcntl(), and kPFErrUnlocking.

Referenced by ~XrdSutPFile(), Browse(), XrdSutPFCache::Flush(), Init(), XrdSutPFCache::Load(), ReadEntry(), RemoveEntry(), RetrieveHeader(), SearchEntries(), SearchSpecialEntries(), Trim(), UpdateCount(), UpdateHeader(), and WriteEntry().

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

◆ Init()

bool XrdSutPFile::Init ( const char *  n,
kXR_int32  openmode = kPFEcreate,
kXR_int32  createmode = 0600,
bool  hashtab = 1 
)

Definition at line 236 of file XrdSutPFile.cc.

238 {
239  // (re)initialize PFile
240 
241  // Make sure it is closed
242  Close();
243 
244  // Reset members
245  if (name)
246  delete[] name;
247  name = 0;
248  if (n) {
249  name = new char[strlen(n)+1];
250  if (name)
251  strcpy(name,n);
252  }
253  valid = 0;
254  fFd = -1;
255  fHTutime = -1;
256  if (fHashTable)
257  delete fHashTable;
258  fHashTable = 0;
259 
260  // If name is missing nothing can be done
261  if (!name)
262  return 0;
263 
264  // open modes
265  bool create = (openmode & kPFEcreate);
266  bool leaveopen = (openmode & kPFEopen);
267 
268  // If file does not exists, create it with default header
269  struct stat st;
270  if (stat(name, &st) == -1) {
271  if (errno == ENOENT) {
272  if (create) {
273  if (Open(1,0,0,createmode) > 0) {
274  kXR_int32 ct = (kXR_int32)time(0);
275  XrdSutPFHeader hdr(kDefFileID,kXrdIFVersion,ct,ct,0,0);
276  WriteHeader(hdr);
277  valid = 1;
278  if (!leaveopen)
279  Close();
280  }
281  } else {
282  Err(kPFErrNoFile,"Init",name);
283  }
284  }
285  } else {
286  // Fill the the hash table
287  if (Open(1) > 0) {
288  if (hashtab)
289  UpdateHashTable();
290  valid = 1;
291  if (!leaveopen)
292  Close();
293  }
294  }
295  // We are done
296  return valid;
297 }
int stat(const char *path, struct stat *buf)
#define kPFEopen
Definition: XrdSutPFile.hh:60
@ kPFErrNoFile
Definition: XrdSutPFile.hh:67
#define kDefFileID
Definition: XrdSutPFile.hh:48
#define kPFEcreate
Definition: XrdSutPFile.hh:59
#define kXrdIFVersion
Definition: XrdSutPFile.hh:49

References Close(), Err, kDefFileID, kPFEcreate, kPFEopen, kPFErrNoFile, kXrdIFVersion, Open(), and stat().

Referenced by XrdSutPFile(), XrdSecProtocolpwd::Init(), and main().

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

◆ IsValid()

bool XrdSutPFile::IsValid ( ) const
inline

Definition at line 170 of file XrdSutPFile.hh.

170 { return valid; }

Referenced by XrdSutPFCache::Flush(), XrdSecProtocolpwd::Init(), XrdSutPFCache::Load(), and main().

+ Here is the caller graph for this function:

◆ LastError()

kXR_int32 XrdSutPFile::LastError ( ) const
inline

Definition at line 172 of file XrdSutPFile.hh.

172 { return fError; }

Referenced by main().

+ Here is the caller graph for this function:

◆ LastErrStr()

const char* XrdSutPFile::LastErrStr ( ) const
inline

Definition at line 173 of file XrdSutPFile.hh.

173 { return (const char *)fErrStr.c_str(); }
const char * c_str() const

References XrdOucString::c_str().

Referenced by XrdSutPFCache::Flush(), and XrdSutPFCache::Load().

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

◆ Name()

const char* XrdSutPFile::Name ( ) const
inline

Definition at line 168 of file XrdSutPFile.hh.

168 { return (const char *)name; }

Referenced by XrdSecProtocolpwd::XrdSecProtocolpwd(), GetEntry(), main(), and RemoveEntries().

+ Here is the caller graph for this function:

◆ Open()

kXR_int32 XrdSutPFile::Open ( kXR_int32  opt,
bool *  wasopen = 0,
const char *  nam = 0,
kXR_int32  createmode = 0600 
)

Definition at line 300 of file XrdSutPFile.cc.

302 {
303  // Open the stream, so defining fFd .
304  // Valid options:
305  // 0 read only
306  // 1 read/write append
307  // 2 read/write truncate
308  // For options 1 and 2 the file is created, if not existing,
309  // and permission set to createmode (default: 0600).
310  // If the file name ends with 'XXXXXX' and it does not exist,
311  // it is created as temporary using mkstemp.
312  // The file is also exclusively locked.
313  // If nam is defined it is used as file name
314  // If the file is already open and wasopen is allocated, then *wasopen
315  // is set to true
316  // The file descriptor of the open file is returned
317  XrdOucString copt(opt);
318 
319  // Reset was open flag
320  if (wasopen) *wasopen = 0;
321 
322  // File name must be defined
323  char *fnam = (char *)nam;
324  if (!fnam)
325  fnam = name;
326  if (!fnam)
327  return Err(kPFErrBadInputs,"Open");
328 
329  // If already open, do nothing
330  if (!nam && fFd > -1) {
331  if (opt > 0) {
332  // Make sure that the write flag is set
333  long omode = 0;
334  if (fcntl(fFd, F_GETFL, &omode) != -1) {
335  if (!(omode | O_WRONLY))
336  return Err(kPFErrFileAlreadyOpen,"Open");
337  }
338  }
339  if (wasopen) *wasopen = 1;
340  return fFd;
341  }
342 
343  // Ok, we have a file name ... check if it exists already
344  bool newfile = 0;
345  struct stat st;
346  if (stat(fnam, &st) == -1) {
347  if (errno != ENOENT) {
348  return Err(kPFErrNoFile,"Open",fnam);
349  } else {
350  if (opt == 0)
351  return Err(kPFErrStat,"Open",fnam);
352  newfile = 1;
353  }
354  }
355 
356  // Now open it
357  if (!nam)
358  fFd = -1;
359  kXR_int32 fd = -1;
360  //
361  // If we have to create a new file and the file name ends with
362  // 'XXXXXX', make it temporary with mkstemp
363  char *pn = strstr(fnam,"XXXXXX");
364  if (pn && (pn == (fnam + strlen(fnam) - 6))) {
365  if (opt > 0 && newfile) {
366  fd = mkstemp(fnam);
367  if (fd <= -1)
368  return Err(kPFErrFileOpen,"Open",fnam);
369  }
370  }
371  //
372  // If normal file act according to requests
373  if (fd <= -1) {
374  kXR_int32 mode = 0;
375  switch (opt) {
376  case 2:
377  //
378  // Forcing truncation in Read / Write mode
379  mode |= (O_TRUNC | O_RDWR) ;
380  if (newfile)
381  mode |= O_CREAT ;
382  break;
383  case 1:
384  //
385  // Read / Write
386  mode |= O_RDWR ;
387  if (newfile)
388  mode |= O_CREAT ;
389  break;
390  case 0:
391  //
392  // Read only
393  mode = O_RDONLY ;
394  break;
395  default:
396  //
397  // Unknown option
398  return Err(kPFErrBadOp,"Open",copt.c_str());
399  }
400 
401  // Open file (createmode is only used if O_CREAT is set)
402  fd = open(fnam, mode, createmode);
403  if (fd <= -1)
404  return Err(kPFErrFileOpen,"Open",fnam);
405  }
406 
407  //
408  // Shared or exclusive lock of the whole file
409  int lockmode = (opt > 0) ? (F_WRLCK | F_RDLCK) : F_RDLCK;
410  int lck = kMaxLockTries;
411  int rc = 0;
412  while (lck && rc == -1) {
413  struct flock flck;
414  memset(&flck, 0, sizeof(flck));
415  flck.l_type = lockmode;
416  flck.l_whence = SEEK_SET;
417  if ((rc = fcntl(fd, F_SETLK, &flck)) == 0)
418  break;
419  struct timespec lftp, rqtp = {1, 0};
420  while (nanosleep(&rqtp, &lftp) < 0 && errno == EINTR) {
421  rqtp.tv_sec = lftp.tv_sec;
422  rqtp.tv_nsec = lftp.tv_nsec;
423  }
424  }
425  if (rc == -1) {
426  if (errno == EACCES || errno == EAGAIN) {
427  // File locked by other process
428  int pid = -1;
429  struct flock flck;
430  memset(&flck, 0, sizeof(flck));
431  flck.l_type = lockmode;
432  flck.l_whence = SEEK_SET;
433  if (fcntl(fd,F_GETLK,&flck) != -1)
434  pid = flck.l_pid;
435  close(fd);
436  return Err(kPFErrFileLocked,"Open",fnam,(const char *)&pid);
437  } else {
438  // Error
439  return Err(kPFErrLocking,"Open",fnam,(const char *)&fd);
440  }
441  }
442 
443  // Ok, we got the file open and locked
444  if (!nam)
445  fFd = fd;
446  return fd;
447 }
int open(const char *path, int oflag,...)
@ kPFErrFileLocked
Definition: XrdSutPFile.hh:74
@ kPFErrBadInputs
Definition: XrdSutPFile.hh:65
@ kPFErrStat
Definition: XrdSutPFile.hh:69
@ kPFErrBadOp
Definition: XrdSutPFile.hh:79
@ kPFErrFileOpen
Definition: XrdSutPFile.hh:70
@ kPFErrLocking
Definition: XrdSutPFile.hh:72
@ kPFErrFileAlreadyOpen
Definition: XrdSutPFile.hh:66
#define kMaxLockTries
Definition: XrdSutPFile.hh:62

References XrdOucString::c_str(), close, Err, fcntl(), kMaxLockTries, kPFErrBadInputs, kPFErrBadOp, kPFErrFileAlreadyOpen, kPFErrFileLocked, kPFErrFileOpen, kPFErrLocking, kPFErrNoFile, kPFErrStat, open(), and stat().

Referenced by Browse(), Init(), ReadEntry(), RemoveEntry(), RetrieveHeader(), SearchEntries(), SearchSpecialEntries(), Trim(), UpdateCount(), UpdateHeader(), and WriteEntry().

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

◆ ReadCount()

kXR_int32 XrdSutPFile::ReadCount ( const char *  nm,
int &  cnt 
)
inline

Definition at line 184 of file XrdSutPFile.hh.

184 { return UpdateCount(nm,&cnt,0); }
kXR_int32 UpdateCount(const char *nm, int *cnt=0, int step=1, bool reset=0)
Definition: XrdSutPFile.cc:795

References UpdateCount().

+ Here is the call graph for this function:

◆ ReadEntry() [1/2]

kXR_int32 XrdSutPFile::ReadEntry ( const char *  name,
XrdSutPFEntry ent,
int  opt = 0 
)

Definition at line 909 of file XrdSutPFile.cc.

911 {
912  // Read entry with tag from file
913  // If it does not exist, if opt == 1 search also for wild-card
914  // matching entries; if more than 1 return the one that matches
915  // the best, base on the number of characters matching.
916  // If more wild-card entries have the same level of matching,
917  // the first found is returned.
918  ent.Reset();
919 
920  // Make sure that we got a tag (otherwise we can't do nothing)
921  if (!tag)
922  return Err(kPFErrBadInputs,"ReadEntry");
923 
924  // Make sure we got an open stream
925  bool wasopen = 0;
926  if (Open(1 &wasopen) < 0)
927  return -1;
928 
929  // Read the header
930  XrdSutPFHeader header;
931  if (ReadHeader(header) < 0) {
932  if (!wasopen) Close();
933  return -1;
934  }
935 
936  // Check if the HashTable needs to be updated
937  if (fHashTable && header.itime > fHTutime) {
938  // Update the table
939  if (UpdateHashTable() < 0) {
940  if (!wasopen) Close();
941  return -1;
942  }
943  }
944  //
945  // Get index entry associated with tag, if any
946  XrdSutPFEntInd ind;
947  bool found = 0;
948  if (fHashTable) {
949  kXR_int32 *reftmp = fHashTable->Find(tag);
950  kXR_int32 refofs = reftmp ? *reftmp : -1;
951  if (refofs > 0) {
952  // Read it out
953  if (ReadInd(refofs, ind) < 0) {
954  if (!wasopen) Close();
955  return -1;
956  }
957  found = 1;
958  }
959  } else {
960  // Get offset of the first index entry
961  kXR_int32 indofs = header.indofs;
962  while (indofs > 0) {
963  // Read it out
964  if (ReadInd(indofs, ind) < 0) {
965  if (!wasopen) Close();
966  return -1;
967  }
968  // Check compatibility
969  if (strlen(ind.name) == strlen(tag)) {
970  if (!strncmp(ind.name,tag,strlen(tag))) {
971  found = 1;
972  break;
973  }
974  }
975  // Next index entry
976  indofs = ind.nxtofs;
977  }
978  }
979  //
980  // If not found and requested, try also wild-cards
981  if (!found && opt == 1) {
982  //
983  // If > 1 we will keep the best matching, i.e. the one
984  // matching most of the chars in tag
985  kXR_int32 refofs = -1;
986  kXR_int32 nmmax = 0;
987  kXR_int32 iofs = header.indofs;
988  XrdOucString stag(tag);
989  while (iofs) {
990  //
991  // Read it out
992  if (ReadInd(iofs, ind) < 0) {
993  if (!wasopen) Close();
994  return -1;
995  }
996  //
997  // Check compatibility, if active
998  if (ind.entofs > 0) {
999  int match = stag.matches(ind.name);
1000  if (match > nmmax && ind.entofs > 0) {
1001  nmmax = match;
1002  refofs = iofs;
1003  }
1004  }
1005  //
1006  // Next index entry
1007  iofs = ind.nxtofs;
1008  }
1009  //
1010  // Read it out
1011  if (refofs > 0) {
1012  if (ReadInd(refofs, ind) < 0) {
1013  if (!wasopen) Close();
1014  return -1;
1015  }
1016  found = 1;
1017  }
1018  }
1019 
1020  // Read the entry, if found
1021  kXR_int32 nr = 0;
1022  if (found) {
1023 
1024  // Read entry if active
1025  if (ind.entofs) {
1026  if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
1027  if (!wasopen) Close();
1028  return -1;
1029  }
1030  // Fill the name
1031  ent.SetName(ind.name);
1032  }
1033  }
1034 
1035  // Close the file
1036  if (!wasopen) Close();
1037 
1038  return nr;
1039 }
T * Find(const char *KeyVal, time_t *KeyTime=0)
Definition: XrdOucHash.icc:160
void SetName(const char *n=0)

References Close(), XrdSutPFEntInd::entofs, Err, XrdOucHash< T >::Find(), XrdSutPFHeader::indofs, XrdSutPFHeader::itime, kPFErrBadInputs, XrdOucString::matches(), XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, Open(), XrdSutPFEntry::Reset(), and XrdSutPFEntry::SetName().

Referenced by XrdSutPFCache::Flush(), GetEntry(), XrdSecProtocolpwd::Init(), and main().

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

◆ ReadEntry() [2/2]

kXR_int32 XrdSutPFile::ReadEntry ( kXR_int32  ofs,
XrdSutPFEntry ent 
)

Definition at line 1042 of file XrdSutPFile.cc.

1043 {
1044  // Read entry at ofs from file
1045 
1046  // Make sure that ofs makes sense
1047  if (ofs <= 0)
1048  return Err(kPFErrBadInputs,"ReadEntry");
1049 
1050  // Make sure we got an open stream
1051  bool wasopen = 0;
1052  if (Open(1, &wasopen) < 0)
1053  return -1;
1054 
1055  kXR_int32 nr = 0;
1056 
1057  // Read index entry out
1058  XrdSutPFEntInd ind;
1059  if (ReadInd(ofs, ind) < 0) {
1060  if (!wasopen) Close();
1061  return -1;
1062  }
1063 
1064  // Read entry
1065  if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
1066  if (!wasopen) Close();
1067  return -1;
1068  }
1069 
1070  // Fill the name
1071  ent.SetName(ind.name);
1072 
1073  // Close the file
1074  if (!wasopen) Close();
1075 
1076  return nr;
1077 }

References Close(), XrdSutPFEntInd::entofs, Err, kPFErrBadInputs, XrdSutPFEntInd::name, Open(), and XrdSutPFEntry::SetName().

+ Here is the call graph for this function:

◆ RemoveEntries()

kXR_int32 XrdSutPFile::RemoveEntries ( const char *  name,
char  opt 
)

Definition at line 2014 of file XrdSutPFile.cc.

2015 {
2016  // Remove entries whose tag is compatible with 'tag', according
2017  // to compatibility option 'opt'.
2018  // For opt = 0 tags starting with 'tag'
2019  // for opt = 1 tags containing the wild card '*' are matched.
2020  // Return number of entries removed
2021  EPNAME("PFile::RemoveEntries");
2022 
2023  //
2024  // Get number of entries related
2025  int nm = SearchEntries(tag,opt);
2026  if (nm) {
2027  DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
2028  //
2029  // Book vector for offsets
2030  int *ofs = new int[nm];
2031  //
2032  // Get number of entries related
2033  SearchEntries(tag,0,ofs,nm);
2034  //
2035  // Read entries now
2036  int i = 0;
2037  for (; i < nm ; i++) {
2038  if (RemoveEntry(ofs[i]) == 0) {
2039  DEBUG("entry for tag '"<<tag<<"' removed from file");
2040  } else {
2041  DEBUG("entry for tag '"<<tag<<"' not found in file");
2042  }
2043  }
2044  } else {
2045  DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
2046  }
2047  // We are done
2048  return nm;
2049 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
const char * Name() const
Definition: XrdSutPFile.hh:168
kXR_int32 SearchEntries(const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
kXR_int32 RemoveEntry(const char *name)

References DEBUG, EPNAME, Name(), RemoveEntry(), and SearchEntries().

+ Here is the call graph for this function:

◆ RemoveEntry() [1/2]

kXR_int32 XrdSutPFile::RemoveEntry ( const char *  name)

Definition at line 1080 of file XrdSutPFile.cc.

1081 {
1082  // Remove entry with tag from file
1083  // The entry is set inactive, so that it is hidden and it will
1084  // be physically removed at next Trim
1085 
1086  // Make sure that we got a tag (otherwise we can't do nothing)
1087  if (!tag || !strlen(tag))
1088  return Err(kPFErrBadInputs,"RemoveEntry");
1089 
1090  // Make sure we got an open stream
1091  if (Open(1) < 0)
1092  return -1;
1093 
1094  // Read the header
1095  XrdSutPFHeader header;
1096  if (ReadHeader(header) < 0) {
1097  Close();
1098  return -1;
1099  }
1100 
1101  // Check if the HashTable needs to be updated
1102  if (fHashTable && header.itime > fHTutime) {
1103  // Update the table
1104  if (UpdateHashTable() < 0) {
1105  Close();
1106  return -1;
1107  }
1108  }
1109 
1110  // Get offset of the index entry associated with tag, if any
1111  XrdSutPFEntInd ind;
1112  bool found = 0;
1113  kXR_int32 indofs = -1;
1114  if (fHashTable) {
1115  kXR_int32 *indtmp = fHashTable->Find(tag);
1116  indofs = indtmp ? *indtmp : indofs;
1117  if (indofs > 0) {
1118  // Read it out
1119  if (ReadInd(indofs, ind) < 0) {
1120  Close();
1121  return -1;
1122  }
1123  found = 1;
1124  }
1125  } else {
1126  // Get offset of the first index entry
1127  indofs = header.indofs;
1128  while (indofs > 0) {
1129  // Read it out
1130  if (ReadInd(indofs, ind) < 0) {
1131  Close();
1132  return -1;
1133  }
1134  // Check compatibility
1135  if (strlen(ind.name) == strlen(tag)) {
1136  if (!strncmp(ind.name,tag,strlen(tag))) {
1137  found = 1;
1138  break;
1139  }
1140  }
1141  // Next index entry
1142  indofs = ind.nxtofs;
1143  }
1144  }
1145  //
1146  // Get entry now, if index found
1147  if (found) {
1148  // Reset entry area
1149  short status = kPFE_inactive;
1150  if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
1151  Close();
1152  return Err(kPFErrSeek,"RemoveEntry",
1153  "SEEK_SET",(const char *)&fFd);
1154  }
1155  while (write(fFd, &status, sizeof(short)) < 0 &&
1156  errno == EINTR) errno = 0;
1157  // Reset entry area
1158  if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
1159  Close();
1160  return -1;
1161  }
1162  // Set entofs to null
1163  ind.entofs = 0;
1164  if (WriteInd(indofs, ind) < 0) {
1165  Close();
1166  return -1;
1167  }
1168  // Count as unused bytes
1169  header.jnksiz += ind.entsiz;
1170  // Decrease number of entries
1171  header.entries--;
1172  // Update times
1173  header.ctime = (kXR_int32)time(0);
1174  header.itime = header.ctime;
1175  // Update header
1176  if (WriteHeader(header) < 0) {
1177  Close();
1178  return -1;
1179  }
1180 
1181  // Ok: close the file and return
1182  Close();
1183  return 0;
1184  }
1185 
1186  // Close the file
1187  Close();
1188  // entry non-existing
1189  return -1;
1190 }
off_t lseek(int fildes, off_t offset, int whence)
ssize_t write(int fildes, const void *buf, size_t nbyte)
@ kPFE_inactive
@ kPFErrSeek
Definition: XrdSutPFile.hh:75
kXR_int32 entsiz
Definition: XrdSutPFile.hh:89

References Close(), XrdSutPFHeader::ctime, XrdSutPFEntInd::entofs, XrdSutPFHeader::entries, XrdSutPFEntInd::entsiz, Err, XrdOucHash< T >::Find(), XrdSutPFHeader::indofs, XrdSutPFHeader::itime, XrdSutPFHeader::jnksiz, kPFE_inactive, kPFErrBadInputs, kPFErrSeek, lseek(), XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, Open(), and write().

Referenced by main(), and RemoveEntries().

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

◆ RemoveEntry() [2/2]

kXR_int32 XrdSutPFile::RemoveEntry ( kXR_int32  ofs)

Definition at line 1193 of file XrdSutPFile.cc.

1194 {
1195  // Remove entry at entry index offset ofs from file
1196  // The entry is set inactive, so that it is hidden and it will
1197  // be physically removed at next Trim
1198 
1199  // Make sure that we got a tag (otherwise we can't do nothing)
1200  if (ofs <= 0)
1201  return Err(kPFErrBadInputs,"RemoveEntry");
1202 
1203  // Make sure we got an open stream
1204  if (Open(1) < 0)
1205  return -1;
1206 
1207  // Read the header
1208  XrdSutPFHeader header;
1209  if (ReadHeader(header) < 0) {
1210  Close();
1211  return -1;
1212  }
1213 
1214  // Check if the HashTable needs to be updated
1215  if (header.itime > fHTutime) {
1216  // Update the table
1217  if (UpdateHashTable() < 0) {
1218  Close();
1219  return -1;
1220  }
1221  }
1222  //
1223  // Read it out
1224  XrdSutPFEntInd ind;
1225  if (ReadInd(ofs, ind) < 0) {
1226  Close();
1227  return -1;
1228  }
1229  //
1230  // Reset entry area
1231  short status = kPFE_inactive;
1232  if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
1233  Close();
1234  return Err(kPFErrSeek,"RemoveEntry",
1235  "SEEK_SET",(const char *)&fFd);
1236  }
1237  while (write(fFd, &status, sizeof(short)) < 0 &&
1238  errno == EINTR) errno = 0;
1239  // Reset entry area
1240  if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
1241  Close();
1242  return -1;
1243  }
1244  // Set entofs to null
1245  ind.entofs = 0;
1246  if (WriteInd(ofs, ind) < 0) {
1247  Close();
1248  return -1;
1249  }
1250  // Count as unused bytes
1251  header.jnksiz += ind.entsiz;
1252  // Decrease number of entries
1253  header.entries--;
1254  // Update times
1255  header.ctime = (kXR_int32)time(0);
1256  header.itime = header.ctime;
1257  // Update header
1258  if (WriteHeader(header) < 0) {
1259  Close();
1260  return -1;
1261  }
1262  //
1263  // Ok: close the file and return
1264  Close();
1265  return 0;
1266 }

References Close(), XrdSutPFHeader::ctime, XrdSutPFEntInd::entofs, XrdSutPFHeader::entries, XrdSutPFEntInd::entsiz, Err, XrdSutPFHeader::itime, XrdSutPFHeader::jnksiz, kPFE_inactive, kPFErrBadInputs, kPFErrSeek, lseek(), Open(), and write().

+ Here is the call graph for this function:

◆ ResetCount()

kXR_int32 XrdSutPFile::ResetCount ( const char *  nm)
inline

Definition at line 183 of file XrdSutPFile.hh.

183 { return UpdateCount(nm,0,0,1); }

References UpdateCount().

+ Here is the call graph for this function:

◆ RetrieveHeader()

kXR_int32 XrdSutPFile::RetrieveHeader ( XrdSutPFHeader hd)

Definition at line 503 of file XrdSutPFile.cc.

504 {
505  // Retrieve number of entries in the file
506 
507  //
508  // Open the file
509  bool wasopen = 0;
510  if (Open(1, &wasopen) < 0)
511  return -1;
512 
513  // Read header
514  kXR_int32 rc = ReadHeader(hd);
515 
516  // Close the file
517  if (!wasopen) Close();
518 
519  return rc;
520 }

References Close(), and Open().

Referenced by Trim().

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

◆ SearchEntries()

kXR_int32 XrdSutPFile::SearchEntries ( const char *  name,
char  opt,
kXR_int32 ofs = 0,
kXR_int32  nofs = 1 
)

Definition at line 2052 of file XrdSutPFile.cc.

2054 {
2055  // Get offsets of the first nofs entries whose tag is compatible
2056  // with 'tag', according to compatibility option 'opt'.
2057  // For opt = 0 tags starting with 'tag' are searched for;
2058  // For opt = 1 tags containing the wild card '*' matching tag
2059  // are searched for.
2060  // For opt = 2 tags matching tag are searched for; tag may contain
2061  // the wild card '*'.
2062  // The caller is responsible for memory pointed by 'ofs'.
2063  // Return number of entries found (<= nofs).
2064  // If ofs = 0, return total number of entries matching the
2065  // condition.
2066 
2067  // Make sure that we got a tag
2068  if (!tag)
2069  return Err(kPFErrBadInputs,"SearchEntries");
2070 
2071  // Make sure we got an open stream
2072  bool wasopen = 0;
2073  if (Open(1,&wasopen) < 0)
2074  return -1;
2075 
2076  // Read the header
2077  XrdSutPFHeader header;
2078  if (ReadHeader(header) < 0) {
2079  if (!wasopen) Close();
2080  return -1;
2081  }
2082 
2083  // Get offset of the first index entry
2084  kXR_int32 indofs = header.indofs;
2085 
2086  // Scan entries
2087  kXR_int32 no = 0;
2088  XrdOucString smatch;
2089  if (opt == 1)
2090  smatch.assign(tag, 0);
2091  while (indofs) {
2092 
2093  // Read it out
2094  XrdSutPFEntInd ind;
2095  if (ReadInd(indofs, ind) < 0) {
2096  if (!wasopen) Close();
2097  return -1;
2098  }
2099 
2100  // Check compatibility
2101  int match = 0;
2102  if (opt == 0) {
2103  if (!strncmp(ind.name,tag,strlen(tag)))
2104  match = 1;
2105  } else if (opt == 1) {
2106  match = smatch.matches(ind.name);
2107  } else if (opt == 2) {
2108  smatch.assign(ind.name, 0);
2109  match = smatch.matches(tag);
2110  }
2111 
2112  if (match > 0 && ind.entofs > 0) {
2113  no++;
2114  if (ofs) {
2115  ofs[no-1] = indofs;
2116  if (no == nofs) {
2117  // We are done
2118  break;
2119  }
2120  }
2121  }
2122 
2123  // Next index entry
2124  indofs = ind.nxtofs;
2125  }
2126 
2127  // Close the file
2128  if (!wasopen) Close();
2129 
2130  return no;
2131 }
void assign(const char *s, int j, int k=-1)
int matches(const char *s, char wch=' *')

References XrdOucString::assign(), Close(), XrdSutPFEntInd::entofs, Err, XrdSutPFHeader::indofs, kPFErrBadInputs, XrdOucString::matches(), XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, and Open().

Referenced by main(), and RemoveEntries().

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

◆ SearchSpecialEntries()

kXR_int32 XrdSutPFile::SearchSpecialEntries ( kXR_int32 ofs = 0,
kXR_int32  nofs = 1 
)

Definition at line 2134 of file XrdSutPFile.cc.

2136 {
2137  // Get offsets of the first nofs entries with status
2138  // kPFE_special.
2139  // The caller is responsible for memory pointed by 'ofs'.
2140  // Return number of entries found (<= nofs).
2141  // If ofs = 0, return total number of special entries.
2142 
2143  // Make sure we got an open stream
2144  bool wasopen = 0;
2145  if (Open(1,&wasopen) < 0)
2146  return -1;
2147 
2148  // Read the header
2149  XrdSutPFHeader header;
2150  if (ReadHeader(header) < 0) {
2151  if (!wasopen) Close();
2152  return -1;
2153  }
2154 
2155  // Get offset of the first index entry
2156  kXR_int32 indofs = header.indofs;
2157 
2158  // Scan entries
2159  kXR_int32 no = 0;
2160  while (indofs) {
2161 
2162  // Read index
2163  XrdSutPFEntInd ind;
2164  if (ReadInd(indofs, ind) < 0) {
2165  if (!wasopen) Close();
2166  return -1;
2167  }
2168 
2169  // If active ...
2170  if (ind.entofs > 0) {
2171 
2172  // Read entry out
2173  XrdSutPFEntry ent;
2174  if (ReadEnt(ind.entofs, ent) < 0) {
2175  if (!wasopen) Close();
2176  return -1;
2177  }
2178  // If special ...
2179  if (ent.status == kPFE_special) {
2180  // Record the offset ...
2181  no++;
2182  if (ofs) {
2183  ofs[no-1] = indofs;
2184  if (no == nofs) {
2185  // We are done
2186  break;
2187  }
2188  }
2189  }
2190  }
2191 
2192  // Next index entry
2193  indofs = ind.nxtofs;
2194  }
2195 
2196  // Close the file
2197  if (!wasopen) Close();
2198 
2199  return no;
2200 }

References Close(), XrdSutPFEntInd::entofs, XrdSutPFHeader::indofs, kPFE_special, XrdSutPFEntInd::nxtofs, Open(), and XrdSutPFEntry::status.

Referenced by Browse().

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

◆ Trim()

kXR_int32 XrdSutPFile::Trim ( const char *  fbak = 0)

Definition at line 1795 of file XrdSutPFile.cc.

1796 {
1797  // Trim away unreachable entries from the file
1798  // Previous content is save in a file name fbak, the default
1799  // being 'name'.bak
1800  EPNAME("PFile::Trim");
1801 
1802  // Retrieve header, first, to check if there is anything to trim
1803  XrdSutPFHeader header;
1804  if (RetrieveHeader(header) < 0)
1805  return -1;
1806  if (header.jnksiz <= 0) {
1807  DEBUG("nothing to trim - return ");
1808  return -1;
1809  }
1810 
1811  // Get name of backup file
1812  char *nbak = (char *)fbak;
1813  if (!nbak) {
1814  // Use default
1815  nbak = new char[strlen(name)+5];
1816  if (!nbak)
1817  return Err(kPFErrOutOfMemory,"Trim");
1818  sprintf(nbak,"%s.bak",name);
1819  DEBUG("backup file: "<<nbak);
1820  }
1821 
1822  // Move file
1823  if (rename(name,nbak) == -1)
1824  return Err(kPFErrFileRename,"Trim",name,nbak);
1825 
1826  // Create new file
1827  int fdnew = Open(1);
1828  if (fdnew < 0)
1829  return -1;
1830 
1831  // Open backup file
1832  int fdbck = Open(1,0,nbak);
1833  if (fdbck < 0) {
1834  Close();
1835  return -1;
1836  }
1837 
1838  // Read the header from backup file
1839  fFd = fdbck;
1840  if (ReadHeader(header) < 0) {
1841  Close(fdnew); Close(fdbck);
1842  return -1;
1843  }
1844 
1845  // Copy it to new file
1846  fFd = fdnew;
1847  if (WriteHeader(header) < 0) {
1848  Close(fdnew); Close(fdbck);
1849  return -1;
1850  }
1851  kXR_int32 wrofs = lseek(fdnew, 0, SEEK_CUR);
1852  if (wrofs == -1) {
1853  Close(fdnew); Close(fdbck);
1854  return Err(kPFErrSeek,"Trim",
1855  "SEEK_CUR",(const char *)&fdnew);
1856  }
1857 
1858  // Read active entries now and save them to new file
1859  bool firstind = 1;
1860  XrdSutPFEntInd ind, indlast;
1861  XrdSutPFEntry ent;
1862 
1863  kXR_int32 nxtofs = header.indofs;
1864  kXR_int32 lastofs = nxtofs;
1865 
1866  while (nxtofs) {
1867 
1868  // Read index entry
1869  fFd = fdbck;
1870  if (ReadInd(nxtofs,ind) < 0) {
1871  Close(fdnew); Close(fdbck);
1872  return -1;
1873  }
1874 
1875  // Get Next index entry before updating index entry
1876  nxtofs = ind.nxtofs;
1877 
1878  // Read entry, if active
1879  if (ind.entofs > 0) {
1880  fFd = fdbck;
1881  if (ReadEnt(ind.entofs,ent) < 0) {
1882  Close(fdnew); Close(fdbck);
1883  return -1;
1884  }
1885  // Update index entry
1886  ind.entofs = wrofs;
1887 
1888  // Write active entry
1889  fFd = fdnew;
1890  if (WriteEnt(wrofs,ent) < 0) {
1891  Close(fdnew); Close(fdbck);
1892  return -1;
1893  }
1894 
1895  // Update write offset
1896  if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1897  Close(fdnew); Close(fdbck);
1898  return Err(kPFErrSeek,"Trim",
1899  "SEEK_CUR",(const char *)&fdnew);
1900  }
1901 
1902  if (firstind) {
1903  // Update header
1904  header.indofs = wrofs;
1905  firstind = 0;
1906  } else {
1907  // Update previous index entry
1908  indlast.nxtofs = wrofs;
1909  fFd = fdnew;
1910  if (WriteInd(lastofs,indlast) < 0) {
1911  Close(fdnew); Close(fdbck);
1912  return -1;
1913  }
1914  }
1915 
1916  // Save this index for later updates
1917  indlast = ind;
1918  lastofs = wrofs;
1919 
1920  // Last index entry, for now
1921  ind.nxtofs = 0;
1922 
1923  // Write active index entry
1924  fFd = fdnew;
1925  if (WriteInd(wrofs,ind) < 0) {
1926  Close(fdnew); Close(fdbck);
1927  return -1;
1928  }
1929 
1930  // Update write offset
1931  if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1932  Close(fdnew); Close(fdbck);
1933  return Err(kPFErrSeek,"Trim",
1934  "SEEK_CUR",(const char *)&fdnew);
1935  }
1936  }
1937  }
1938 
1939  // Close backup file
1940  Close(fdbck);
1941  fFd = fdnew;
1942 
1943  // Update header
1944  header.ctime = (kXR_int32)time(0);
1945  header.itime = header.ctime;
1946  header.jnksiz = 0;
1947 
1948  // Copy it to new file
1949  if (WriteHeader(header) < 0) {
1950  Close();;
1951  return -1;
1952  }
1953 
1954  // Close the file
1955  Close();
1956 
1957  return 0;
1958 }
int rename(const char *oldpath, const char *newpath)
@ kPFErrOutOfMemory
Definition: XrdSutPFile.hh:77
@ kPFErrFileRename
Definition: XrdSutPFile.hh:68
kXR_int32 RetrieveHeader(XrdSutPFHeader &hd)
Definition: XrdSutPFile.cc:503

References Close(), XrdSutPFHeader::ctime, DEBUG, XrdSutPFEntInd::entofs, EPNAME, Err, XrdSutPFHeader::indofs, XrdSutPFHeader::itime, XrdSutPFHeader::jnksiz, kPFErrFileRename, kPFErrOutOfMemory, kPFErrSeek, lseek(), XrdSutPFEntInd::nxtofs, Open(), rename(), and RetrieveHeader().

Referenced by main().

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

◆ UpdateCount()

kXR_int32 XrdSutPFile::UpdateCount ( const char *  nm,
int *  cnt = 0,
int  step = 1,
bool  reset = 0 
)

Definition at line 795 of file XrdSutPFile.cc.

797 {
798  // Update counter for entry with 'tag', if any.
799  // If reset is true, counter is firts reset.
800  // The counter is updated by 'step'.
801  // Default: no reset, increase by 1.
802  // If cnt is defined, fill it with the updated counter.
803  // Returns 0 or -1 in case of error
804 
805  // Make sure that we got a tag (otherwise we can't do nothing)
806  if (!tag)
807  return Err(kPFErrBadInputs,"UpdateCount");
808 
809  // Make sure we got an open stream
810  if (Open(1) < 0)
811  return -1;
812 
813  // Read the header
814  XrdSutPFHeader header;
815  if (ReadHeader(header) < 0) {
816  Close();
817  return -1;
818  }
819 
820  // Check if the HashTable needs to be updated
821  if (fHashTable && header.itime > fHTutime) {
822  // Update the table
823  if (UpdateHashTable() < 0) {
824  Close();
825  return -1;
826  }
827  }
828  //
829  // Get index entry associated with tag, if any
830  XrdSutPFEntInd ind;
831  bool found = 0;
832  if (fHashTable) {
833  kXR_int32 *refofs = fHashTable->Find(tag);
834  if (*refofs > 0) {
835  // Read it out
836  if (ReadInd(*refofs, ind) < 0) {
837  Close();
838  return -1;
839  }
840  found = 1;
841  }
842  } else {
843  // Get offset of the first index entry
844  kXR_int32 indofs = header.indofs;
845  while (indofs > 0) {
846  // Read it out
847  if (ReadInd(indofs, ind) < 0) {
848  Close();
849  return -1;
850  }
851  // Check compatibility
852  if (strlen(ind.name) == strlen(tag)) {
853  if (!strncmp(ind.name,tag,strlen(tag))) {
854  found = 1;
855  break;
856  }
857  }
858  // Next index entry
859  indofs = ind.nxtofs;
860  }
861  }
862  //
863  // Read the entry, if found
864  XrdSutPFEntry ent;
865  bool changed = 0;
866  if (found) {
867 
868  // Read entry if active
869  if (ind.entofs) {
870  if (ReadEnt(ind.entofs, ent) < 0) {
871  Close();
872  return -1;
873  }
874  //
875  // Reset counter if required
876  if (reset && ent.cnt != 0) {
877  changed = 1;
878  ent.cnt = 0;
879  }
880  //
881  // Update counter
882  if (step != 0) {
883  changed = 1;
884  ent.cnt += step;
885  }
886  //
887  // Update entry in file, if anything changed
888  if (changed) {
889  ent.mtime = (kXR_int32)time(0);
890  if (WriteEnt(ind.entofs, ent) < 0) {
891  Close();
892  return -1;
893  }
894  }
895  //
896  // Fill output
897  if (cnt)
898  *cnt = ent.cnt;
899  }
900  }
901 
902  // Close the file
903  Close();
904 
905  return 0;
906 }

References Close(), XrdSutPFEntry::cnt, XrdSutPFEntInd::entofs, Err, XrdOucHash< T >::Find(), XrdSutPFHeader::indofs, XrdSutPFHeader::itime, kPFErrBadInputs, XrdSutPFEntry::mtime, XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, and Open().

Referenced by ReadCount(), and ResetCount().

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

◆ UpdateHeader()

kXR_int32 XrdSutPFile::UpdateHeader ( XrdSutPFHeader  hd)

Definition at line 484 of file XrdSutPFile.cc.

485 {
486  // Write/Update header to beginning of file
487 
488  //
489  // Open the file
490  if (Open(1) < 0)
491  return -1;
492 
493  // Write
494  kXR_int32 nw = WriteHeader(hd);
495 
496  // Close the file
497  Close();
498 
499  return nw;
500 }

References Close(), and Open().

+ Here is the call graph for this function:

◆ WriteEntry()

kXR_int32 XrdSutPFile::WriteEntry ( XrdSutPFEntry  ent)

Definition at line 585 of file XrdSutPFile.cc.

586 {
587  // Write entry to file
588  // Look first if an entry with the same name exists: in such
589  // case try to overwrite the allocated file region; if the space
590  // is not enough, set the existing entry inactive and write
591  // the new entry at the end of the file, updating all the
592  // pointers.
593  // File must be opened in read/write mode (O_RDWR).
594 
595  // Make sure that the entry is named (otherwise we can't do nothing)
596  if (!ent.name)
597  return Err(kPFErrBadInputs,"WriteEntry");
598 
599  //
600  // Ready to write: open the file
601  bool wasopen = 0;
602  if (Open(1, &wasopen) < 0)
603  return -1;
604 
605  kXR_int32 ofs = 0;
606  kXR_int32 nw = 0;
607  kXR_int32 indofs = 0;
608  // Read the header
609  XrdSutPFHeader header;
610  if (ReadHeader(header) < 0) {
611  if (!wasopen) Close();
612  return -1;
613  }
614  if ((ofs = lseek(fFd, 0, SEEK_CUR)) == -1) {
615  if (!wasopen) Close();
616  return Err(kPFErrSeek,"WriteEntry","SEEK_CUR",(const char *)&fFd);
617  }
618 
619  XrdSutPFEntInd ind;
620  // If first entry, write it, update the info and return
621  if (header.entries == 0) {
622  if ((nw = WriteEnt(ofs, ent)) < 0) {
623  if (!wasopen) Close();
624  return -1;
625  }
626  ind.SetName(ent.name);
627  ind.nxtofs = 0;
628  ind.entofs = ofs;
629  ind.entsiz = nw;
630  indofs = ofs + nw;
631  if (WriteInd(indofs, ind) < 0) {
632  if (!wasopen) Close();
633  return -1;
634  }
635  // Update header
636  header.entries = 1;
637  header.indofs = indofs;
638  header.ctime = time(0);
639  header.itime = header.ctime;
640  if (WriteHeader(header) < 0) {
641  if (!wasopen) Close();
642  return -1;
643  }
644  if (!wasopen) Close();
645  return nw;
646  }
647 
648  // First Localize existing entry, if any
649  kXR_int32 nr = 1;
650  bool found = 0;
651  indofs = header.indofs;
652  kXR_int32 lastindofs = indofs;
653  while (!found && nr > 0 && indofs > 0) {
654  nr = ReadInd(indofs, ind);
655  if (nr) {
656  if (ind.entofs > 0 && !strcmp(ent.name,ind.name)) {
657  found = 1;
658  break;
659  }
660  lastindofs = indofs;
661  indofs = ind.nxtofs;
662  }
663  }
664 
665  //
666  // If an entry already exists and there is enough space to
667  // store the update, write the update at the already allocated
668  // space; if not, add it at the end.
669  if (found) {
670  // Update
671  kXR_int32 ct = 0;
672  if (ind.entsiz >= ent.Length()) {
673  // The offset is set inside ...
674  if ((nw = WriteEnt(ind.entofs, ent)) < 0) {
675  if (!wasopen) Close();
676  return -1;
677  }
678  } else {
679  // Add it at the end
680  kXR_int32 entofs = 0;
681  if ((entofs = lseek(fFd, 0, SEEK_END)) == -1) {
682  if (!wasopen) Close();
683  return Err(kPFErrSeek,"WriteEntry",
684  "SEEK_END",(const char *)&fFd);
685  }
686  if ((nw = WriteEnt(entofs, ent)) < 0) {
687  if (!wasopen) Close();
688  return -1;
689  }
690  // Set existing entry inactive
691  kXR_int32 wrtofs = ind.entofs;
692  if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
693  if (!wasopen) Close();
694  return Err(kPFErrSeek,"WriteEntry",
695  "SEEK_SET",(const char *)&fFd);
696  }
697  short status = kPFE_inactive;
698  while (write(fFd, &status, sizeof(short)) < 0 &&
699  errno == EINTR) errno = 0;
700  // Reset entry area
701  if (Reset(wrtofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
702  if (!wasopen) Close();
703  return -1;
704  }
705  // Count as unused bytes
706  header.jnksiz += ind.entsiz;
707  if (lseek(fFd, kOfsJnkSiz, SEEK_SET) == -1) {
708  if (!wasopen) Close();
709  return Err(kPFErrSeek,"WriteEntry",
710  "SEEK_SET",(const char *)&fFd);
711  }
712  while (write(fFd, &header.jnksiz, sizeof(kXR_int32)) < 0 &&
713  errno == EINTR) errno = 0;
714  // Update the entry index and new size
715  wrtofs = indofs + 2*sizeof(kXR_int32);
716  if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
717  if (!wasopen) Close();
718  return Err(kPFErrSeek,"WriteEntry",
719  "SEEK_SET",(const char *)&fFd);
720  }
721  while (write(fFd, &entofs, sizeof(kXR_int32)) < 0 &&
722  errno == EINTR) errno = 0;
723  while (write(fFd, &nw, sizeof(kXR_int32)) < 0 &&
724  errno == EINTR) errno = 0;
725  // Update time of change of index
726  ct = (kXR_int32)time(0);
727  header.itime = ct;
728  if (lseek(fFd, kOfsItime, SEEK_SET) == -1) {
729  if (!wasopen) Close();
730  return Err(kPFErrSeek,"WriteEntry",
731  "SEEK_SET",(const char *)&fFd);
732  }
733  while (write(fFd, &header.itime, sizeof(kXR_int32)) < 0 &&
734  errno == EINTR) errno = 0;
735  }
736  // Update time of change in header
737  header.ctime = (ct > 0) ? ct : time(0);
738  if (lseek(fFd, kOfsCtime, SEEK_SET) == -1) {
739  if (!wasopen) Close();
740  return Err(kPFErrSeek,"WriteEntry",
741  "SEEK_SET",(const char *)&fFd);
742  }
743  while (write(fFd, &header.ctime, sizeof(kXR_int32)) < 0 &&
744  errno == EINTR) errno = 0;
745  if (!wasopen) Close();
746  return nw;
747  }
748 
749  //
750  // If new name, add the entry at the end
751  if ((ofs = lseek(fFd, 0, SEEK_END)) == -1) {
752  if (!wasopen) Close();
753  return Err(kPFErrSeek,"WriteEntry",
754  "SEEK_END",(const char *)&fFd);
755  }
756  if ((nw = WriteEnt(ofs, ent)) < 0) {
757  if (!wasopen) Close();
758  return -1;
759  }
760  //
761  // Create new index entry
762  XrdSutPFEntInd newind(ent.name, 0, ofs, nw);
763  if (WriteInd(ofs+nw, newind) < 0) {
764  if (!wasopen) Close();
765  return -1;
766  }
767  //
768  // Update previous index entry
769  ind.nxtofs = ofs + nw;
770  kXR_int32 wrtofs = lastindofs + sizeof(kXR_int32);
771  if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
772  if (!wasopen) Close();
773  return Err(kPFErrSeek,"WriteEntry",
774  "SEEK_SET",(const char *)&fFd);
775  }
776  while (write(fFd, &ind.nxtofs, sizeof(kXR_int32)) < 0 &&
777  errno == EINTR) errno = 0;
778 
779  // Update header
780  header.entries += 1;
781  header.ctime = time(0);
782  header.itime = header.ctime;
783  if (WriteHeader(header) < 0) {
784  if (!wasopen) Close();
785  return -1;
786  }
787 
788  // Close the file
789  if (!wasopen) Close();
790 
791  return nw;
792 }
#define kOfsJnkSiz
Definition: XrdSutPFile.hh:57
#define kOfsCtime
Definition: XrdSutPFile.hh:53
#define kOfsItime
Definition: XrdSutPFile.hh:54
void SetName(const char *n=0)
Definition: XrdSutPFile.cc:78
kXR_int32 Length() const

References Close(), XrdSutPFHeader::ctime, XrdSutPFEntInd::entofs, XrdSutPFHeader::entries, XrdSutPFEntInd::entsiz, Err, XrdSutPFHeader::indofs, XrdSutPFHeader::itime, XrdSutPFHeader::jnksiz, kOfsCtime, kOfsItime, kOfsJnkSiz, kPFE_inactive, kPFErrBadInputs, kPFErrSeek, XrdSutPFEntry::Length(), lseek(), XrdSutPFEntry::name, XrdSutPFEntInd::name, XrdSutPFEntInd::nxtofs, Open(), XrdSutPFEntInd::SetName(), and write().

Referenced by XrdSutPFCache::Flush(), and main().

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

Friends And Related Function Documentation

◆ XrdSutPFCache

friend class XrdSutPFCache
friend

Definition at line 123 of file XrdSutPFile.hh.


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