XRootD
Loading...
Searching...
No Matches
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)

References Init().

Referenced by XrdSutPFile(), and XrdSutPFCache.

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

References XrdSutPFile().

Here is the call graph for this function:

◆ ~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)

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:305
@ kPFE_special
kXR_int32 len
kXR_int32 entofs
kXR_int32 nxtofs
kXR_int32 mtime
XrdSutPFBuf buf3
XrdSutPFBuf buf1
XrdSutPFBuf buf2
XrdSutPFBuf buf4
kXR_int32 itime
kXR_int32 entries
kXR_int32 version
kXR_int32 ctime
kXR_int32 jnksiz
kXR_int32 indofs
char fileID[kFileIDSize]
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)

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)
#define close(a)
Definition XrdPosix.hh:48
@ kPFErrUnlocking

References close, Err, and kPFErrUnlocking.

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

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}
#define stat(a, b)
Definition XrdPosix.hh:101
#define kPFEopen
@ kPFErrNoFile
#define kDefFileID
#define kPFEcreate
#define kXrdIFVersion

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

Referenced by XrdSutPFile(), 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(), 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(); }

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

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 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}
#define open
Definition XrdPosix.hh:76
@ kPFErrFileLocked
@ kPFErrBadInputs
@ kPFErrStat
@ kPFErrBadOp
@ kPFErrFileOpen
@ kPFErrLocking
@ kPFErrFileAlreadyOpen
#define kMaxLockTries

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

Referenced by Browse(), Init(), ReadEntry(), ReadEntry(), RemoveEntry(), 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)

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}
void SetName(const char *n=0)

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

Referenced by XrdSutPFCache::Flush(), GetEntry(), 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)
#define EPNAME(x)
kXR_int32 SearchEntries(const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
const char * Name() const
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}
#define lseek(a, b, c)
Definition XrdPosix.hh:52
#define write(a, b, c)
Definition XrdPosix.hh:115
@ kPFE_inactive
@ kPFErrSeek
kXR_int32 entsiz

References Close(), XrdSutPFHeader::ctime, XrdSutPFEntInd::entofs, XrdSutPFHeader::entries, XrdSutPFEntInd::entsiz, Err, 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}
#define rename(a, b)
Definition XrdPosix.hh:92
@ kPFErrOutOfMemory
@ kPFErrFileRename
kXR_int32 RetrieveHeader(XrdSutPFHeader &hd)

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, 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
#define kOfsCtime
#define kOfsItime
if(ec< 0) ec
void SetName(const char *n=0)
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, XrdSutPFEntInd::name, XrdSutPFEntry::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:

◆ XrdSutPFCache

friend class XrdSutPFCache
friend

Definition at line 123 of file XrdSutPFile.hh.

References XrdSutPFile(), kPFEcreate, and XrdSutPFCache.

Referenced by XrdSutPFCache.


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