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.

{
// Constructor
name = 0;
if (n) {
name = new char[strlen(n)+1];
if (name)
strcpy(name,n);
}
valid = 0;
fFd = -1;
fHTutime = -1;
fHashTable = 0;
valid = Init(n, openmode, createmode, hashtab);
}
XrdSutPFile::Init
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
Definition XrdSutPFile.cc:236

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.

{
// Copy constructor
name = 0;
if (f.name) {
name = new char[strlen(f.name)+1];
if (name)
strcpy(name,f.name);
}
fFd = f.fFd ;
}

References XrdSutPFile().

Here is the call graph for this function:

## ~XrdSutPFile()

XrdSutPFile::~XrdSutPFile | ( |  | ) |

virtual

Definition at line 221 of file XrdSutPFile.cc.

{
// Destructor
if (name)
delete[] name;
name = 0;
if (fHashTable)
delete fHashTable;
fHashTable = 0;
Close();
}
XrdSutPFile::Close
kXR_int32 Close(kXR_int32 d=-1)
Definition XrdSutPFile.cc:450

References Close().

Here is the call graph for this function:

## Member Function Documentation

## Browse()

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

Definition at line 1624 of file XrdSutPFile.cc.

{
// Display the content of the file
// Make sure we got an open stream
if (Open(1) < 0)
return -1;
// Read header
XrdSutPFHeader hdr;
if (ReadHeader(hdr) < 0) {
Close();
return -1;
}
// Time strings
struct tm tst;
char sctime[256] = {0};
time_t ttmp = hdr.ctime;
localtime_r(&ttmp,&tst);
asctime_r(&tst,sctime);
sctime[strlen(sctime)-1] = 0;
char sitime[256] = {0};
ttmp = hdr.itime;
localtime_r(&ttmp,&tst);
asctime_r(&tst,sitime);
sitime[strlen(sitime)-1] = 0;
// Default is stdout
FILE *out = oout ? (FILE *)oout : stdout;
fprintf(out,"//-----------------------------------------------------"
"--------------------//\n");
fprintf(out,"//\n");
fprintf(out,"// File: %s\n",name);
fprintf(out,"// ID: %s\n",hdr.fileID);
fprintf(out,"// Version: %d\n",hdr.version);
fprintf(out,"// Last change : %s (%d sec)\n",sctime,hdr.ctime);
fprintf(out,"// Index change: %s (%d sec)\n",sitime,hdr.itime);
fprintf(out,"//\n");
fprintf(out,"// Number of Entries: %d\n",hdr.entries);
fprintf(out,"// Bytes unreachable: %d\n",hdr.jnksiz);
fprintf(out,"//\n");
if (hdr.entries > 0) {
// Special entries first, if any
kXR_int32 ns = SearchSpecialEntries();
if (ns > 0) {
// Allocate space for offsets
kXR_int32 *sofs = new kXR_int32[ns];
if (sofs) {
// Get offsets
ns = SearchSpecialEntries(sofs,ns);
fprintf(out,"// Special entries (%d):\n",ns);
int i = 0;
for (; i<ns; i++) {
// Read entry index at ofs
XrdSutPFEntInd ind;
if (ReadInd(sofs[i], ind) < 0) {
Close();
return -1;
}
if (ind.entofs) {
// Read entry
XrdSutPFEntry ent;
if (ReadEnt(ind.entofs, ent) < 0) {
Close();
return -1;
}
char smt[20] = {0};
XrdSutTimeString(ent.mtime,smt);
std::string buffer;
char buf[2048] = {0};
memset(buf,0,2048);
sprintf(buf,"// #%d mod:%s",i+1,smt);
buffer = buf;
sprintf(buf," name:%s",ind.name);
buffer += buf;
fprintf(out,"%s\n",buffer.c_str());
buffer.clear();
sprintf(buf,"// buf");
buffer = buf;
if (ent.cnt == 1) {
if (ent.buf1.len && ent.buf1.buf)
{
sprintf(buf,": %.*s",ent.buf1.len,ent.buf1.buf);
buffer += buf;
}
if (ent.buf2.len && ent.buf2.buf)
{
sprintf(buf,": %.*s",ent.buf2.len,ent.buf2.buf);
buffer += buf;
}
if (ent.buf3.len && ent.buf3.buf)
{
sprintf(buf,": %.*s",ent.buf3.len,ent.buf3.buf);
buffer += buf;
}
if (ent.buf4.len && ent.buf4.buf)
{
sprintf(buf,": %.*s",ent.buf4.len,ent.buf4.buf);
buffer += buf;
}
} else {
sprintf(buf,":%d:%d:%d:%d",
ent.buf1.len,ent.buf2.len,ent.buf3.len,
ent.buf4.len);
buffer += buf;
buffer += " (protected)";
}
fprintf(out,"%s\n",buf);
}
}
fprintf(out,"//\n");
delete[] sofs;
}
}
if (hdr.entries > ns)
fprintf(out,"// Normal entries (%d):\n",hdr.entries-ns);
kXR_int32 nn = 0;
kXR_int32 nxtofs = hdr.indofs;
while (nxtofs) {
// Read entry index at ofs
XrdSutPFEntInd ind;
if (ReadInd(nxtofs, ind) < 0) {
Close();
return -3;
}
if (ind.entofs) {
// Read entry
XrdSutPFEntry ent;
if (ReadEnt(ind.entofs, ent) < 0) {
Close();
return -4;
}
if (ent.status != kPFE_special) {
char smt[20] = {0};
XrdSutTimeString(ent.mtime,smt);
nn++;
fprintf(out,
"// #:%d st:%d cn:%d buf:%d,%d,%d,%d mod:%s name:%s\n",
nn,ent.status,ent.cnt,ent.buf1.len,ent.buf2.len,ent.buf3.len,
ent.buf4.len,smt,ind.name);
}
}
// Read next
nxtofs = ind.nxtofs;
}
fprintf(out,"//\n");
}
fprintf(out,"//-----------------------------------------------------"
"--------------------//\n");
// Close the file
Close();
return 0;
}
kXR_int32
int kXR_int32
Definition XPtypes.hh:89
XrdSutTimeString
int XrdSutTimeString(int t, char *st, int opt)
Definition XrdSutAux.cc:305
kPFE_special
@ kPFE_special
Definition XrdSutPFEntry.hh:47
XrdSutPFBuf::buf
char * buf
Definition XrdSutPFEntry.hh:57
XrdSutPFBuf::len
kXR_int32 len
Definition XrdSutPFEntry.hh:58
XrdSutPFEntInd::entofs
kXR_int32 entofs
Definition XrdSutPFile.hh:88
XrdSutPFEntInd::nxtofs
kXR_int32 nxtofs
Definition XrdSutPFile.hh:87
XrdSutPFEntInd::name
char * name
Definition XrdSutPFile.hh:86
XrdSutPFEntry::mtime
kXR_int32 mtime
Definition XrdSutPFEntry.hh:83
XrdSutPFEntry::buf3
XrdSutPFBuf buf3
Definition XrdSutPFEntry.hh:86
XrdSutPFEntry::buf1
XrdSutPFBuf buf1
Definition XrdSutPFEntry.hh:84
XrdSutPFEntry::status
short status
Definition XrdSutPFEntry.hh:81
XrdSutPFEntry::buf2
XrdSutPFBuf buf2
Definition XrdSutPFEntry.hh:85
XrdSutPFEntry::buf4
XrdSutPFBuf buf4
Definition XrdSutPFEntry.hh:87
XrdSutPFEntry::cnt
short cnt
Definition XrdSutPFEntry.hh:82
XrdSutPFHeader::itime
kXR_int32 itime
Definition XrdSutPFile.hh:107
XrdSutPFHeader::entries
kXR_int32 entries
Definition XrdSutPFile.hh:108
XrdSutPFHeader::version
kXR_int32 version
Definition XrdSutPFile.hh:105
XrdSutPFHeader::ctime
kXR_int32 ctime
Definition XrdSutPFile.hh:106
XrdSutPFHeader::jnksiz
kXR_int32 jnksiz
Definition XrdSutPFile.hh:110
XrdSutPFHeader::indofs
kXR_int32 indofs
Definition XrdSutPFile.hh:109
XrdSutPFHeader::fileID
char fileID[kFileIDSize]
Definition XrdSutPFile.hh:104
XrdSutPFile::SearchSpecialEntries
kXR_int32 SearchSpecialEntries(kXR_int32 *ofs=0, kXR_int32 nofs=1)
Definition XrdSutPFile.cc:2134
XrdSutPFile::Open
kXR_int32 Open(kXR_int32 opt, bool *wasopen=0, const char *nam=0, kXR_int32 createmode=0600)
Definition XrdSutPFile.cc:300

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

Referenced by main().

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

## Close()

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

Definition at line 450 of file XrdSutPFile.cc.

{
// Close the open stream or descriptor fd, if > -1 .
// The file is unlocked before.
// If not open, do nothing
if (fd < 0)
fd = fFd;
if (fd < 0)
return 0;
//
// Unlock the file
struct flock flck;
memset(&flck, 0, sizeof(flck));
flck.l_type = F_UNLCK;
flck.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &flck) == -1) {
close(fd);
return Err(kPFErrUnlocking,"Close",(const char *)&fd);
}
//
// Close it
close(fd);
// Reset file descriptor
if (fd == fFd)
fFd = -1;
return 0;
}
Err
#define Err(p, a, b, c)
Definition XrdNetSocket.cc:81
close
#define close(a)
Definition XrdPosix.hh:48
kPFErrUnlocking
@ kPFErrUnlocking
Definition XrdSutPFile.hh:73

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.

{
// (re)initialize PFile
// Make sure it is closed
Close();
// Reset members
if (name)
delete[] name;
name = 0;
if (n) {
name = new char[strlen(n)+1];
if (name)
strcpy(name,n);
}
valid = 0;
fFd = -1;
fHTutime = -1;
if (fHashTable)
delete fHashTable;
fHashTable = 0;
// If name is missing nothing can be done
if (!name)
return 0;
// open modes
bool create = (openmode & kPFEcreate);
bool leaveopen = (openmode & kPFEopen);
// If file does not exists, create it with default header
struct stat st;
if (stat(name, &st) == -1) {
if (errno == ENOENT) {
if (create) {
if (Open(1,0,0,createmode) > 0) {
kXR_int32 ct = (kXR_int32)time(0);
XrdSutPFHeader hdr(kDefFileID,kXrdIFVersion,ct,ct,0,0);
WriteHeader(hdr);
valid = 1;
if (!leaveopen)
Close();
}
} else {
Err(kPFErrNoFile,"Init",name);
}
}
} else {
// Fill the the hash table
if (Open(1) > 0) {
if (hashtab)
UpdateHashTable();
valid = 1;
if (!leaveopen)
Close();
}
}
// We are done
return valid;
}
stat
#define stat(a, b)
Definition XrdPosix.hh:101
kPFEopen
#define kPFEopen
Definition XrdSutPFile.hh:60
kPFErrNoFile
@ kPFErrNoFile
Definition XrdSutPFile.hh:67
kDefFileID
#define kDefFileID
Definition XrdSutPFile.hh:48
kPFEcreate
#define kPFEcreate
Definition XrdSutPFile.hh:59
kXrdIFVersion
#define kXrdIFVersion
Definition XrdSutPFile.hh:49

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.

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

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

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

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

{
// Open the stream, so defining fFd .
// Valid options:
// 0 read only
// 1 read/write append
// 2 read/write truncate
// For options 1 and 2 the file is created, if not existing,
// and permission set to createmode (default: 0600).
// If the file name ends with 'XXXXXX' and it does not exist,
// it is created as temporary using mkstemp.
// The file is also exclusively locked.
// If nam is defined it is used as file name
// If the file is already open and wasopen is allocated, then *wasopen
// is set to true
// The file descriptor of the open file is returned
XrdOucString copt(opt);
// Reset was open flag
if (wasopen) *wasopen = 0;
// File name must be defined
char *fnam = (char *)nam;
if (!fnam)
fnam = name;
if (!fnam)
return Err(kPFErrBadInputs,"Open");
// If already open, do nothing
if (!nam && fFd > -1) {
if (opt > 0) {
// Make sure that the write flag is set
long omode = 0;
if (fcntl(fFd, F_GETFL, &omode) != -1) {
if (!(omode | O_WRONLY))
return Err(kPFErrFileAlreadyOpen,"Open");
}
}
if (wasopen) *wasopen = 1;
return fFd;
}
// Ok, we have a file name ... check if it exists already
bool newfile = 0;
struct stat st;
if (stat(fnam, &st) == -1) {
if (errno != ENOENT) {
return Err(kPFErrNoFile,"Open",fnam);
} else {
if (opt == 0)
return Err(kPFErrStat,"Open",fnam);
newfile = 1;
}
}
// Now open it
if (!nam)
fFd = -1;
kXR_int32 fd = -1;
//
// If we have to create a new file and the file name ends with
// 'XXXXXX', make it temporary with mkstemp
char *pn = strstr(fnam,"XXXXXX");
if (pn && (pn == (fnam + strlen(fnam) - 6))) {
if (opt > 0 && newfile) {
fd = mkstemp(fnam);
if (fd <= -1)
return Err(kPFErrFileOpen,"Open",fnam);
}
}
//
// If normal file act according to requests
if (fd <= -1) {
kXR_int32 mode = 0;
switch (opt) {
case 2:
//
// Forcing truncation in Read / Write mode
mode |= (O_TRUNC | O_RDWR) ;
if (newfile)
mode |= O_CREAT ;
break;
case 1:
//
// Read / Write
mode |= O_RDWR ;
if (newfile)
mode |= O_CREAT ;
break;
case 0:
//
// Read only
mode = O_RDONLY ;
break;
default:
//
// Unknown option
return Err(kPFErrBadOp,"Open",copt.c_str());
}
// Open file (createmode is only used if O_CREAT is set)
fd = open(fnam, mode, createmode);
if (fd <= -1)
return Err(kPFErrFileOpen,"Open",fnam);
}
//
// Shared or exclusive lock of the whole file
int lockmode = (opt > 0) ? (F_WRLCK | F_RDLCK) : F_RDLCK;
int lck = kMaxLockTries;
int rc = 0;
while (lck && rc == -1) {
struct flock flck;
memset(&flck, 0, sizeof(flck));
flck.l_type = lockmode;
flck.l_whence = SEEK_SET;
if ((rc = fcntl(fd, F_SETLK, &flck)) == 0)
break;
struct timespec lftp, rqtp = {1, 0};
while (nanosleep(&rqtp, &lftp) < 0 && errno == EINTR) {
rqtp.tv_sec = lftp.tv_sec;
rqtp.tv_nsec = lftp.tv_nsec;
}
}
if (rc == -1) {
if (errno == EACCES || errno == EAGAIN) {
// File locked by other process
int pid = -1;
struct flock flck;
memset(&flck, 0, sizeof(flck));
flck.l_type = lockmode;
flck.l_whence = SEEK_SET;
if (fcntl(fd,F_GETLK,&flck) != -1)
pid = flck.l_pid;
close(fd);
return Err(kPFErrFileLocked,"Open",fnam,(const char *)&pid);
} else {
// Error
return Err(kPFErrLocking,"Open",fnam,(const char *)&fd);
}
}
// Ok, we got the file open and locked
if (!nam)
fFd = fd;
return fd;
}
open
#define open
Definition XrdPosix.hh:76
kPFErrFileLocked
@ kPFErrFileLocked
Definition XrdSutPFile.hh:74
kPFErrBadInputs
@ kPFErrBadInputs
Definition XrdSutPFile.hh:65
kPFErrStat
@ kPFErrStat
Definition XrdSutPFile.hh:69
kPFErrBadOp
@ kPFErrBadOp
Definition XrdSutPFile.hh:79
kPFErrFileOpen
@ kPFErrFileOpen
Definition XrdSutPFile.hh:70
kPFErrLocking
@ kPFErrLocking
Definition XrdSutPFile.hh:72
kPFErrFileAlreadyOpen
@ kPFErrFileAlreadyOpen
Definition XrdSutPFile.hh:66
kMaxLockTries
#define kMaxLockTries
Definition XrdSutPFile.hh:62

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.

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

References UpdateCount().

Here is the call graph for this function:

## ReadEntry() [1/2]

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

Definition at line 909 of file XrdSutPFile.cc.

{
// Read entry with tag from file
// If it does not exist, if opt == 1 search also for wild-card
// matching entries; if more than 1 return the one that matches
// the best, base on the number of characters matching.
// If more wild-card entries have the same level of matching,
// the first found is returned.
ent.Reset();
// Make sure that we got a tag (otherwise we can't do nothing)
if (!tag)
return Err(kPFErrBadInputs,"ReadEntry");
// Make sure we got an open stream
bool wasopen = 0;
if (Open(1 &wasopen) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
// Check if the HashTable needs to be updated
if (fHashTable && header.itime > fHTutime) {
// Update the table
if (UpdateHashTable() < 0) {
if (!wasopen) Close();
return -1;
}
}
//
// Get index entry associated with tag, if any
XrdSutPFEntInd ind;
bool found = 0;
if (fHashTable) {
kXR_int32 *reftmp = fHashTable->Find(tag);
kXR_int32 refofs = reftmp ? *reftmp : -1;
if (refofs > 0) {
// Read it out
if (ReadInd(refofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
found = 1;
}
} else {
// Get offset of the first index entry
kXR_int32 indofs = header.indofs;
while (indofs > 0) {
// Read it out
if (ReadInd(indofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
// Check compatibility
if (strlen(ind.name) == strlen(tag)) {
if (!strncmp(ind.name,tag,strlen(tag))) {
found = 1;
break;
}
}
// Next index entry
indofs = ind.nxtofs;
}
}
//
// If not found and requested, try also wild-cards
if (!found && opt == 1) {
//
// If > 1 we will keep the best matching, i.e. the one
// matching most of the chars in tag
kXR_int32 refofs = -1;
kXR_int32 nmmax = 0;
kXR_int32 iofs = header.indofs;
XrdOucString stag(tag);
while (iofs) {
//
// Read it out
if (ReadInd(iofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
//
// Check compatibility, if active
if (ind.entofs > 0) {
int match = stag.matches(ind.name);
if (match > nmmax && ind.entofs > 0) {
nmmax = match;
refofs = iofs;
}
}
//
// Next index entry
iofs = ind.nxtofs;
}
//
// Read it out
if (refofs > 0) {
if (ReadInd(refofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
found = 1;
}
}
// Read the entry, if found
kXR_int32 nr = 0;
if (found) {
// Read entry if active
if (ind.entofs) {
if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
// Fill the name
ent.SetName(ind.name);
}
}
// Close the file
if (!wasopen) Close();
return nr;
}
XrdSutPFEntry::SetName
void SetName(const char *n=0)
Definition XrdSutPFEntry.cc:136
XrdSutPFEntry::Reset
void Reset()
Definition XrdSutPFEntry.cc:119

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.

{
// Read entry at ofs from file
// Make sure that ofs makes sense
if (ofs <= 0)
return Err(kPFErrBadInputs,"ReadEntry");
// Make sure we got an open stream
bool wasopen = 0;
if (Open(1, &wasopen) < 0)
return -1;
kXR_int32 nr = 0;
// Read index entry out
XrdSutPFEntInd ind;
if (ReadInd(ofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
// Read entry
if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
// Fill the name
ent.SetName(ind.name);
// Close the file
if (!wasopen) Close();
return nr;
}

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.

{
// Remove entries whose tag is compatible with 'tag', according
// to compatibility option 'opt'.
// For opt = 0 tags starting with 'tag'
// for opt = 1 tags containing the wild card '*' are matched.
// Return number of entries removed
EPNAME("PFile::RemoveEntries");
//
// Get number of entries related
int nm = SearchEntries(tag,opt);
if (nm) {
DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
//
// Book vector for offsets
int *ofs = new int[nm];
//
// Get number of entries related
SearchEntries(tag,0,ofs,nm);
//
// Read entries now
int i = 0;
for (; i < nm ; i++) {
if (RemoveEntry(ofs[i]) == 0) {
DEBUG("entry for tag '"<<tag<<"' removed from file");
} else {
DEBUG("entry for tag '"<<tag<<"' not found in file");
}
}
} else {
DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
}
// We are done
return nm;
}
DEBUG
#define DEBUG(x)
Definition XrdBwmTrace.hh:54
EPNAME
#define EPNAME(x)
Definition XrdBwmTrace.hh:56
XrdSutPFile::SearchEntries
kXR_int32 SearchEntries(const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
Definition XrdSutPFile.cc:2052
XrdSutPFile::Name
const char * Name() const
Definition XrdSutPFile.hh:168
XrdSutPFile::RemoveEntry
kXR_int32 RemoveEntry(const char *name)
Definition XrdSutPFile.cc:1080

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.

{
// Remove entry with tag from file
// The entry is set inactive, so that it is hidden and it will
// be physically removed at next Trim
// Make sure that we got a tag (otherwise we can't do nothing)
if (!tag || !strlen(tag))
return Err(kPFErrBadInputs,"RemoveEntry");
// Make sure we got an open stream
if (Open(1) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
Close();
return -1;
}
// Check if the HashTable needs to be updated
if (fHashTable && header.itime > fHTutime) {
// Update the table
if (UpdateHashTable() < 0) {
Close();
return -1;
}
}
// Get offset of the index entry associated with tag, if any
XrdSutPFEntInd ind;
bool found = 0;
kXR_int32 indofs = -1;
if (fHashTable) {
kXR_int32 *indtmp = fHashTable->Find(tag);
indofs = indtmp ? *indtmp : indofs;
if (indofs > 0) {
// Read it out
if (ReadInd(indofs, ind) < 0) {
Close();
return -1;
}
found = 1;
}
} else {
// Get offset of the first index entry
indofs = header.indofs;
while (indofs > 0) {
// Read it out
if (ReadInd(indofs, ind) < 0) {
Close();
return -1;
}
// Check compatibility
if (strlen(ind.name) == strlen(tag)) {
if (!strncmp(ind.name,tag,strlen(tag))) {
found = 1;
break;
}
}
// Next index entry
indofs = ind.nxtofs;
}
}
//
// Get entry now, if index found
if (found) {
// Reset entry area
short status = kPFE_inactive;
if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
Close();
return Err(kPFErrSeek,"RemoveEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &status, sizeof(short)) < 0 &&
errno == EINTR) errno = 0;
// Reset entry area
if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
Close();
return -1;
}
// Set entofs to null
ind.entofs = 0;
if (WriteInd(indofs, ind) < 0) {
Close();
return -1;
}
// Count as unused bytes
header.jnksiz += ind.entsiz;
// Decrease number of entries
header.entries--;
// Update times
header.ctime = (kXR_int32)time(0);
header.itime = header.ctime;
// Update header
if (WriteHeader(header) < 0) {
Close();
return -1;
}
// Ok: close the file and return
Close();
return 0;
}
// Close the file
Close();
// entry non-existing
return -1;
}
lseek
#define lseek(a, b, c)
Definition XrdPosix.hh:52
write
#define write(a, b, c)
Definition XrdPosix.hh:115
kPFE_inactive
@ kPFE_inactive
Definition XrdSutPFEntry.hh:41
kPFErrSeek
@ kPFErrSeek
Definition XrdSutPFile.hh:75
XrdSutPFEntInd::entsiz
kXR_int32 entsiz
Definition XrdSutPFile.hh:89

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.

{
// Remove entry at entry index offset ofs from file
// The entry is set inactive, so that it is hidden and it will
// be physically removed at next Trim
// Make sure that we got a tag (otherwise we can't do nothing)
if (ofs <= 0)
return Err(kPFErrBadInputs,"RemoveEntry");
// Make sure we got an open stream
if (Open(1) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
Close();
return -1;
}
// Check if the HashTable needs to be updated
if (header.itime > fHTutime) {
// Update the table
if (UpdateHashTable() < 0) {
Close();
return -1;
}
}
//
// Read it out
XrdSutPFEntInd ind;
if (ReadInd(ofs, ind) < 0) {
Close();
return -1;
}
//
// Reset entry area
short status = kPFE_inactive;
if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
Close();
return Err(kPFErrSeek,"RemoveEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &status, sizeof(short)) < 0 &&
errno == EINTR) errno = 0;
// Reset entry area
if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
Close();
return -1;
}
// Set entofs to null
ind.entofs = 0;
if (WriteInd(ofs, ind) < 0) {
Close();
return -1;
}
// Count as unused bytes
header.jnksiz += ind.entsiz;
// Decrease number of entries
header.entries--;
// Update times
header.ctime = (kXR_int32)time(0);
header.itime = header.ctime;
// Update header
if (WriteHeader(header) < 0) {
Close();
return -1;
}
//
// Ok: close the file and return
Close();
return 0;
}

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.

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

{
// Retrieve number of entries in the file
//
// Open the file
bool wasopen = 0;
if (Open(1, &wasopen) < 0)
return -1;
// Read header
kXR_int32 rc = ReadHeader(hd);
// Close the file
if (!wasopen) Close();
return rc;
}

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.

{
// Get offsets of the first nofs entries whose tag is compatible
// with 'tag', according to compatibility option 'opt'.
// For opt = 0 tags starting with 'tag' are searched for;
// For opt = 1 tags containing the wild card '*' matching tag
// are searched for.
// For opt = 2 tags matching tag are searched for; tag may contain
// the wild card '*'.
// The caller is responsible for memory pointed by 'ofs'.
// Return number of entries found (<= nofs).
// If ofs = 0, return total number of entries matching the
// condition.
// Make sure that we got a tag
if (!tag)
return Err(kPFErrBadInputs,"SearchEntries");
// Make sure we got an open stream
bool wasopen = 0;
if (Open(1,&wasopen) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
// Get offset of the first index entry
kXR_int32 indofs = header.indofs;
// Scan entries
kXR_int32 no = 0;
XrdOucString smatch;
if (opt == 1)
smatch.assign(tag, 0);
while (indofs) {
// Read it out
XrdSutPFEntInd ind;
if (ReadInd(indofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
// Check compatibility
int match = 0;
if (opt == 0) {
if (!strncmp(ind.name,tag,strlen(tag)))
match = 1;
} else if (opt == 1) {
match = smatch.matches(ind.name);
} else if (opt == 2) {
smatch.assign(ind.name, 0);
match = smatch.matches(tag);
}
if (match > 0 && ind.entofs > 0) {
no++;
if (ofs) {
ofs[no-1] = indofs;
if (no == nofs) {
// We are done
break;
}
}
}
// Next index entry
indofs = ind.nxtofs;
}
// Close the file
if (!wasopen) Close();
return no;
}
XrdOucString::assign
void assign(const char *s, int j, int k=-1)
Definition XrdOucString.cc:511
XrdOucString::matches
int matches(const char *s, char wch=' *')
Definition XrdOucString.cc:426

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.

{
// Get offsets of the first nofs entries with status
// kPFE_special.
// The caller is responsible for memory pointed by 'ofs'.
// Return number of entries found (<= nofs).
// If ofs = 0, return total number of special entries.
// Make sure we got an open stream
bool wasopen = 0;
if (Open(1,&wasopen) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
// Get offset of the first index entry
kXR_int32 indofs = header.indofs;
// Scan entries
kXR_int32 no = 0;
while (indofs) {
// Read index
XrdSutPFEntInd ind;
if (ReadInd(indofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
// If active ...
if (ind.entofs > 0) {
// Read entry out
XrdSutPFEntry ent;
if (ReadEnt(ind.entofs, ent) < 0) {
if (!wasopen) Close();
return -1;
}
// If special ...
if (ent.status == kPFE_special) {
// Record the offset ...
no++;
if (ofs) {
ofs[no-1] = indofs;
if (no == nofs) {
// We are done
break;
}
}
}
}
// Next index entry
indofs = ind.nxtofs;
}
// Close the file
if (!wasopen) Close();
return no;
}

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.

{
// Trim away unreachable entries from the file
// Previous content is save in a file name fbak, the default
// being 'name'.bak
EPNAME("PFile::Trim");
// Retrieve header, first, to check if there is anything to trim
XrdSutPFHeader header;
if (RetrieveHeader(header) < 0)
return -1;
if (header.jnksiz <= 0) {
DEBUG("nothing to trim - return ");
return -1;
}
// Get name of backup file
char *nbak = (char *)fbak;
if (!nbak) {
// Use default
nbak = new char[strlen(name)+5];
if (!nbak)
return Err(kPFErrOutOfMemory,"Trim");
sprintf(nbak,"%s.bak",name);
DEBUG("backup file: "<<nbak);
}
// Move file
if (rename(name,nbak) == -1)
return Err(kPFErrFileRename,"Trim",name,nbak);
// Create new file
int fdnew = Open(1);
if (fdnew < 0)
return -1;
// Open backup file
int fdbck = Open(1,0,nbak);
if (fdbck < 0) {
Close();
return -1;
}
// Read the header from backup file
fFd = fdbck;
if (ReadHeader(header) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
// Copy it to new file
fFd = fdnew;
if (WriteHeader(header) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
kXR_int32 wrofs = lseek(fdnew, 0, SEEK_CUR);
if (wrofs == -1) {
Close(fdnew); Close(fdbck);
return Err(kPFErrSeek,"Trim",
"SEEK_CUR",(const char *)&fdnew);
}
// Read active entries now and save them to new file
bool firstind = 1;
XrdSutPFEntInd ind, indlast;
XrdSutPFEntry ent;
kXR_int32 nxtofs = header.indofs;
kXR_int32 lastofs = nxtofs;
while (nxtofs) {
// Read index entry
fFd = fdbck;
if (ReadInd(nxtofs,ind) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
// Get Next index entry before updating index entry
nxtofs = ind.nxtofs;
// Read entry, if active
if (ind.entofs > 0) {
fFd = fdbck;
if (ReadEnt(ind.entofs,ent) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
// Update index entry
ind.entofs = wrofs;
// Write active entry
fFd = fdnew;
if (WriteEnt(wrofs,ent) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
// Update write offset
if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
Close(fdnew); Close(fdbck);
return Err(kPFErrSeek,"Trim",
"SEEK_CUR",(const char *)&fdnew);
}
if (firstind) {
// Update header
header.indofs = wrofs;
firstind = 0;
} else {
// Update previous index entry
indlast.nxtofs = wrofs;
fFd = fdnew;
if (WriteInd(lastofs,indlast) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
}
// Save this index for later updates
indlast = ind;
lastofs = wrofs;
// Last index entry, for now
ind.nxtofs = 0;
// Write active index entry
fFd = fdnew;
if (WriteInd(wrofs,ind) < 0) {
Close(fdnew); Close(fdbck);
return -1;
}
// Update write offset
if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
Close(fdnew); Close(fdbck);
return Err(kPFErrSeek,"Trim",
"SEEK_CUR",(const char *)&fdnew);
}
}
}
// Close backup file
Close(fdbck);
fFd = fdnew;
// Update header
header.ctime = (kXR_int32)time(0);
header.itime = header.ctime;
header.jnksiz = 0;
// Copy it to new file
if (WriteHeader(header) < 0) {
Close();;
return -1;
}
// Close the file
Close();
return 0;
}
rename
#define rename(a, b)
Definition XrdPosix.hh:92
kPFErrOutOfMemory
@ kPFErrOutOfMemory
Definition XrdSutPFile.hh:77
kPFErrFileRename
@ kPFErrFileRename
Definition XrdSutPFile.hh:68
XrdSutPFile::RetrieveHeader
kXR_int32 RetrieveHeader(XrdSutPFHeader &hd)
Definition XrdSutPFile.cc:503

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

Referenced by main().

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

## UpdateCount()

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

Definition at line 795 of file XrdSutPFile.cc.

{
// Update counter for entry with 'tag', if any.
// If reset is true, counter is firts reset.
// The counter is updated by 'step'.
// Default: no reset, increase by 1.
// If cnt is defined, fill it with the updated counter.
// Returns 0 or -1 in case of error
// Make sure that we got a tag (otherwise we can't do nothing)
if (!tag)
return Err(kPFErrBadInputs,"UpdateCount");
// Make sure we got an open stream
if (Open(1) < 0)
return -1;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
Close();
return -1;
}
// Check if the HashTable needs to be updated
if (fHashTable && header.itime > fHTutime) {
// Update the table
if (UpdateHashTable() < 0) {
Close();
return -1;
}
}
//
// Get index entry associated with tag, if any
XrdSutPFEntInd ind;
bool found = 0;
if (fHashTable) {
kXR_int32 *refofs = fHashTable->Find(tag);
if (*refofs > 0) {
// Read it out
if (ReadInd(*refofs, ind) < 0) {
Close();
return -1;
}
found = 1;
}
} else {
// Get offset of the first index entry
kXR_int32 indofs = header.indofs;
while (indofs > 0) {
// Read it out
if (ReadInd(indofs, ind) < 0) {
Close();
return -1;
}
// Check compatibility
if (strlen(ind.name) == strlen(tag)) {
if (!strncmp(ind.name,tag,strlen(tag))) {
found = 1;
break;
}
}
// Next index entry
indofs = ind.nxtofs;
}
}
//
// Read the entry, if found
XrdSutPFEntry ent;
bool changed = 0;
if (found) {
// Read entry if active
if (ind.entofs) {
if (ReadEnt(ind.entofs, ent) < 0) {
Close();
return -1;
}
//
// Reset counter if required
if (reset && ent.cnt != 0) {
changed = 1;
ent.cnt = 0;
}
//
// Update counter
if (step != 0) {
changed = 1;
ent.cnt += step;
}
//
// Update entry in file, if anything changed
if (changed) {
ent.mtime = (kXR_int32)time(0);
if (WriteEnt(ind.entofs, ent) < 0) {
Close();
return -1;
}
}
//
// Fill output
if (cnt)
*cnt = ent.cnt;
}
}
// Close the file
Close();
return 0;
}

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.

{
// Write/Update header to beginning of file
//
// Open the file
if (Open(1) < 0)
return -1;
// Write
kXR_int32 nw = WriteHeader(hd);
// Close the file
Close();
return nw;
}

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.

{
// Write entry to file
// Look first if an entry with the same name exists: in such
// case try to overwrite the allocated file region; if the space
// is not enough, set the existing entry inactive and write
// the new entry at the end of the file, updating all the
// pointers.
// File must be opened in read/write mode (O_RDWR).
// Make sure that the entry is named (otherwise we can't do nothing)
if (!ent.name)
return Err(kPFErrBadInputs,"WriteEntry");
//
// Ready to write: open the file
bool wasopen = 0;
if (Open(1, &wasopen) < 0)
return -1;
kXR_int32 ofs = 0;
kXR_int32 nw = 0;
kXR_int32 indofs = 0;
// Read the header
XrdSutPFHeader header;
if (ReadHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
if ((ofs = lseek(fFd, 0, SEEK_CUR)) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry","SEEK_CUR",(const char *)&fFd);
}
XrdSutPFEntInd ind;
// If first entry, write it, update the info and return
if (header.entries == 0) {
if ((nw = WriteEnt(ofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
ind.SetName(ent.name);
ind.nxtofs = 0;
ind.entofs = ofs;
ind.entsiz = nw;
indofs = ofs + nw;
if (WriteInd(indofs, ind) < 0) {
if (!wasopen) Close();
return -1;
}
// Update header
header.entries = 1;
header.indofs = indofs;
header.ctime = time(0);
header.itime = header.ctime;
if (WriteHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
if (!wasopen) Close();
return nw;
}
// First Localize existing entry, if any
kXR_int32 nr = 1;
bool found = 0;
indofs = header.indofs;
kXR_int32 lastindofs = indofs;
while (!found && nr > 0 && indofs > 0) {
nr = ReadInd(indofs, ind);
if (nr) {
if (ind.entofs > 0 && !strcmp(ent.name,ind.name)) {
found = 1;
break;
}
lastindofs = indofs;
indofs = ind.nxtofs;
}
}
//
// If an entry already exists and there is enough space to
// store the update, write the update at the already allocated
// space; if not, add it at the end.
if (found) {
// Update
kXR_int32 ct = 0;
if (ind.entsiz >= ent.Length()) {
// The offset is set inside ...
if ((nw = WriteEnt(ind.entofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
} else {
// Add it at the end
kXR_int32 entofs = 0;
if ((entofs = lseek(fFd, 0, SEEK_END)) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_END",(const char *)&fFd);
}
if ((nw = WriteEnt(entofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
// Set existing entry inactive
kXR_int32 wrtofs = ind.entofs;
if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
short status = kPFE_inactive;
while (write(fFd, &status, sizeof(short)) < 0 &&
errno == EINTR) errno = 0;
// Reset entry area
if (Reset(wrtofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
if (!wasopen) Close();
return -1;
}
// Count as unused bytes
header.jnksiz += ind.entsiz;
if (lseek(fFd, kOfsJnkSiz, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &header.jnksiz, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
// Update the entry index and new size
wrtofs = indofs + 2*sizeof(kXR_int32);
if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &entofs, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
while (write(fFd, &nw, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
// Update time of change of index
ct = (kXR_int32)time(0);
header.itime = ct;
if (lseek(fFd, kOfsItime, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &header.itime, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
}
// Update time of change in header
header.ctime = (ct > 0) ? ct : time(0);
if (lseek(fFd, kOfsCtime, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &header.ctime, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
if (!wasopen) Close();
return nw;
}
//
// If new name, add the entry at the end
if ((ofs = lseek(fFd, 0, SEEK_END)) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_END",(const char *)&fFd);
}
if ((nw = WriteEnt(ofs, ent)) < 0) {
if (!wasopen) Close();
return -1;
}
//
// Create new index entry
XrdSutPFEntInd newind(ent.name, 0, ofs, nw);
if (WriteInd(ofs+nw, newind) < 0) {
if (!wasopen) Close();
return -1;
}
//
// Update previous index entry
ind.nxtofs = ofs + nw;
kXR_int32 wrtofs = lastindofs + sizeof(kXR_int32);
if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
if (!wasopen) Close();
return Err(kPFErrSeek,"WriteEntry",
"SEEK_SET",(const char *)&fFd);
}
while (write(fFd, &ind.nxtofs, sizeof(kXR_int32)) < 0 &&
errno == EINTR) errno = 0;
// Update header
header.entries += 1;
header.ctime = time(0);
header.itime = header.ctime;
if (WriteHeader(header) < 0) {
if (!wasopen) Close();
return -1;
}
// Close the file
if (!wasopen) Close();
return nw;
}
kOfsJnkSiz
#define kOfsJnkSiz
Definition XrdSutPFile.hh:57
kOfsCtime
#define kOfsCtime
Definition XrdSutPFile.hh:53
kOfsItime
#define kOfsItime
Definition XrdSutPFile.hh:54
if
if(ec< 0) ec
XrdSutPFEntInd::SetName
void SetName(const char *n=0)
Definition XrdSutPFile.cc:78
XrdSutPFEntry::Length
kXR_int32 Length() const
Definition XrdSutPFEntry.hh:93
XrdSutPFEntry::name
char * name
Definition XrdSutPFEntry.hh:80

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:

- XrdSutPFile.hh
- XrdSutPFile.cc