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 1623 of file XrdSutPFile.cc.

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

References close, Err, fcntl(), 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 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}
#define stat(a, b)
Definition XrdPosix.hh:96
#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:71
@ kPFErrFileLocked
@ kPFErrBadInputs
@ kPFErrStat
@ kPFErrBadOp
@ kPFErrFileOpen
@ kPFErrLocking
@ kPFErrFileAlreadyOpen
#define kMaxLockTries

References XrdOucString::c_str(), close, Err, fcntl(), 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 2013 of file XrdSutPFile.cc.

2014{
2015 // Remove entries whose tag is compatible with 'tag', according
2016 // to compatibility option 'opt'.
2017 // For opt = 0 tags starting with 'tag'
2018 // for opt = 1 tags containing the wild card '*' are matched.
2019 // Return number of entries removed
2020 EPNAME("PFile::RemoveEntries");
2021
2022 //
2023 // Get number of entries related
2024 int nm = SearchEntries(tag,opt);
2025 if (nm) {
2026 DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
2027 //
2028 // Book vector for offsets
2029 int *ofs = new int[nm];
2030 //
2031 // Get number of entries related
2032 SearchEntries(tag,0,ofs,nm);
2033 //
2034 // Read entries now
2035 int i = 0;
2036 for (; i < nm ; i++) {
2037 if (RemoveEntry(ofs[i]) == 0) {
2038 DEBUG("entry for tag '"<<tag<<"' removed from file");
2039 } else {
2040 DEBUG("entry for tag '"<<tag<<"' not found in file");
2041 }
2042 }
2043 } else {
2044 DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
2045 }
2046 // We are done
2047 return nm;
2048}
#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:47
#define write(a, b, c)
Definition XrdPosix.hh:110
@ 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 2051 of file XrdSutPFile.cc.

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

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

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 1794 of file XrdSutPFile.cc.

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

Friends And Related Symbol Documentation

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