XRootD
XrdSutPFCache.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S u t C a c h e . c c */
4 /* */
5 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Gerri Ganis for CERN */
7 /* */
8 /* This file is part of the XRootD software suite. */
9 /* */
10 /* XRootD is free software: you can redistribute it and/or modify it under */
11 /* the terms of the GNU Lesser General Public License as published by the */
12 /* Free Software Foundation, either version 3 of the License, or (at your */
13 /* option) any later version. */
14 /* */
15 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
16 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
17 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
18 /* License for more details. */
19 /* */
20 /* You should have received a copy of the GNU Lesser General Public License */
21 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
22 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
23 /* */
24 /* The copyright holder's institutional names and contributor's names may not */
25 /* be used to endorse or promote products derived from this software without */
26 /* specific prior written permission of the institution or contributor. */
27 /******************************************************************************/
28 
29 #include <cstdio>
30 #include <cstdlib>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <ctime>
35 
36 #include "XrdSut/XrdSutPFCache.hh"
37 #include "XrdSut/XrdSutPFile.hh"
38 #include "XrdSut/XrdSutTrace.hh"
39 #include "XrdSut/XrdSutAux.hh"
40 #include "XrdSys/XrdSysTimer.hh"
41 
42 /******************************************************************************/
43 /* */
44 /* For caching temporary information during the authentication handshake */
45 /* */
46 /******************************************************************************/
47 
48 //__________________________________________________________________
50 {
51  // Destructor
52 
53  // We are destroying the cache
54  rwlock.WriteLock();
55 
56  // Cleanup content
57  while (cachemx > -1) {
58  if (cachent[cachemx]) {
59  delete cachent[cachemx];
60  cachent[cachemx] = 0;
61  }
62  cachemx--;
63  }
64  // Cleanup table
65  if (cachent)
66  delete[] cachent;
67 
68  // Done
69  rwlock.UnLock();
70 }
71 
72 //__________________________________________________________________
73 int XrdSutPFCache::Init(int capacity, bool lock)
74 {
75  // Initialize the cache to hold up to capacity entries.
76  // Later on, capacity is double each time more space is needed.
77  // Return 0 if ok, -1 otherwise
78  EPNAME("Cache::Init");
79 
80  // Lock for writing
81  if (lock) rwlock.WriteLock();
82 
83  // Nothing to do if already done
84  if (isinit) {
85  if (lock) rwlock.UnLock();
86  return 0;
87  }
88 
89  // Make sure capacity makes sense; use a default, if not
90  capacity = (capacity > 0) ? capacity : 100;
91 
92  // Allocate
93  cachent = new XrdSutPFEntry *[capacity];
94  if (cachent) {
95  for (int i = 0; i < capacity; i++) { cachent[i] = 0; }
96  cachesz = capacity;
97  DEBUG("cache allocated for "<<cachesz<<" entries");
98 
99  // Update time stamp
100  utime = (kXR_int32)time(0);
101 
102  // Init hash table
103  if (Rehash(0, 0) != 0) {
104  DEBUG("problems initialising hash table");
105  }
106  // UnLock
107  if (lock) rwlock.UnLock();
108  return 0;
109 
110  } else
111  DEBUG("could not allocate cache - out-of-resources ");
112 
113  // Flag has initialized
114  isinit = 1;
115 
116  // UnLock
117  if (lock) rwlock.UnLock();
118  return -1;
119 }
120 
121 //__________________________________________________________________
122 XrdSutPFEntry *XrdSutPFCache::Get(XrdSutPFCacheRef &urRef, const char *ID, bool *wild)
123 {
124  // Retrieve an entry with ID, if any
125  // If wild is defined, search also best matching regular expression
126  // with wildcard '*'; *wild = 0 will indicate exact match,
127  // *wild = 1 wild card compatibility match
128  EPNAME("Cache::Get");
129  XrdSutPFEntry *pfEnt;
130  int i;
131 
132  TRACE(Dump,"locating entry for ID: "<<ID);
133 
134  //
135  // If ID is undefined, do nothing
136  if (!ID || !strlen(ID)) {
137  DEBUG("empty ID !");
138  return (XrdSutPFEntry *)0 ;
139  }
140  if (wild) *wild = 0;
141 
142  if (Rehash() != 0) {
143  DEBUG("problems rehashing");
144  return (XrdSutPFEntry *)0 ;
145  }
146 
147  // Lock for reading
148  XrdSysRWLockHelper isg(rwlock, 1);
149 
150  // Find the entry and lock it. Repeat if we can get a lock.
151  //
152  for (i = 0; i < maxTries; i++)
153  {if ((pfEnt = Get(ID, wild)))
154  {if (pfEnt->pfeMutex.CondLock())
155  {urRef.Set(&(pfEnt->pfeMutex));
156  return pfEnt;
157  }
158  } else return pfEnt;
159  isg.UnLock();
160  XrdSysTimer::Wait(retryMSW);
161  if (Rehash() != 0)
162  {DEBUG("problems rehashing");
163  return (XrdSutPFEntry *)0 ;
164  }
165  isg.Lock(&rwlock, 1);
166  }
167 
168  // Nothing found
169  return (XrdSutPFEntry *)0 ;
170 }
171 
172 //__________________________________________________________________
173 XrdSutPFEntry *XrdSutPFCache::Get(const char *ID, bool *wild)
174 {
175 
176  // Look in the hash first
177  kXR_int32 *ie = hashtable.Find(ID);
178  if (ie && *ie >= 0 && *ie < cachesz) {
179  // Return the associated entry
180  return cachent[*ie];
181  }
182 
183  // If wild cards allowed search sequentially
184  if (wild) {
185  XrdOucString sid(ID);
186  int i = 0, match = 0, nmmax = 0, iref = -1;
187  for (; i <= cachemx; i++) {
188  if (cachent[i]) {
189  match = sid.matches(cachent[i]->name);
190  if (match > nmmax) {
191  nmmax = match;
192  iref = i;
193  }
194  }
195  }
196  if (iref > -1) {
197  *wild = 1;
198  return cachent[iref];
199  }
200  }
201 
202  // Nothing found
203  return (XrdSutPFEntry *)0 ;
204 }
205 
206 //__________________________________________________________________
207 XrdSutPFEntry *XrdSutPFCache::Add(XrdSutPFCacheRef &urRef, const char *ID, bool force)
208 {
209  // Add an entry with ID in cache
210  // Cache buffer is re-allocated with double size, if needed
211  // Hash is updated
212  EPNAME("Cache::Add");
213 
214  //
215  // IF ID is undefined, do nothing
216  if (!ID || !strlen(ID)) {
217  DEBUG("empty ID !");
218  return (XrdSutPFEntry *)0 ;
219  }
220 
221  //
222  // If an entry already exists, return it
223  XrdSutPFEntry *ent = Get(urRef, ID);
224  if (ent)
225  return ent;
226 
227  // Lock for writing
228  XrdSysRWLockHelper isg(rwlock, 0);
229 
230  //
231  // Make sure there enough space for a new entry
232  if (cachemx == cachesz - 1) {
233  //
234  // Duplicate buffer
235  XrdSutPFEntry **newcache = new XrdSutPFEntry *[2*cachesz];
236  if (!newcache) {
237  DEBUG("could not extend cache to size: "<<(2*cachesz));
238  return (XrdSutPFEntry *)0 ;
239  }
240  // Update info
241  cachesz *= 2;
242  //
243  // Copy existing valid entries, calculating real size
244  int i = 0, nmx = 0;
245  for (; i <= cachemx; i++) {
246  if (cachent[i]) {
247  newcache[nmx] = cachent[i];
248  nmx++;
249  }
250  }
251  // update size
252  cachemx = nmx - 1;
253  //
254  // Reset new entries
255  for (i = cachemx + 1; i <= cachemx; i++) {
256  newcache[i] = 0;
257  }
258  //
259  // Cleanup and reassign
260  delete[] cachent;
261  cachent = newcache;
262  //
263  // Force rehash in this case
264  force = 1;
265  }
266  //
267  // The next free
268  int pos = cachemx + 1;
269 
270  //
271  // Add new entry
272  cachent[pos] = new XrdSutPFEntry(ID);
273  if (cachent[pos]) {
274  cachemx = pos;
275  } else {
276  DEBUG("could not allocate space for new cache entry");
277  return (XrdSutPFEntry *)0 ;
278  }
279  // Update time stamp
280  utime = (kXR_int32)time(0);
281 
282  // Rebuild hash table
283  if (Rehash(force, 0) != 0) {
284  DEBUG("problems re-hashing");
285  return (XrdSutPFEntry *)0 ;
286  }
287 
288  // We are done (we can lock the entry without a wait)
289  urRef.Lock(&(cachent[pos]->pfeMutex));
290  return cachent[pos];
291 }
292 
293 //__________________________________________________________________
294 bool XrdSutPFCache::Remove(const char *ID, int opt)
295 {
296  // If opt==1 remove entry with name matching exactly ID from cache
297  // If opt==0 all entries with names starting with ID are removed
298  // Return 1 if ok, 0 otherwise
299  EPNAME("Cache::Remove");
300 
301  //
302  // IF ID is undefined, do nothing
303  if (!ID || !strlen(ID)) {
304  DEBUG("empty ID !");
305  return 0 ;
306  }
307 
308  // Lock for writing
309  XrdSysRWLockHelper isg(rwlock, 0);
310 
311  if (Rehash(0, 0) != 0) {
312  DEBUG("problems rehashing");
313  return 0 ;
314  }
315 
316  bool found = 0;
317  if (opt == 1) {
318  int pos = -1;
319  // Look in the hash first
320  kXR_int32 *ie = hashtable.Find(ID);
321  if (*ie >= 0 && *ie < cachesz) {
322  // Return the associated entry
323  pos = *ie;
324  }
325 
326  //
327  // Check if pos makes sense
328  if (cachent[pos] && !strcmp(cachent[pos]->name,ID)) {
329  if (!Delete(cachent[pos])) DEBUG("Delete deferred for " <<ID);
330  cachent[pos] = 0;
331  // We are done, if not the one at highest index
332  if (pos < cachemx)
333  return 1;
334  // We update the highest index
335  found = 1;
336  }
337  } else {
338  // Loop over entries
339  int i = cachemx;
340  for (; i >= 0; i--) {
341  if (cachent[i]) {
342  if (!strncmp(cachent[i]->name,ID,strlen(ID))) {
343  if (!Delete(cachent[i])) DEBUG("Delete deferred for " <<ID);
344  cachent[i] = 0;
345  found = 1;
346  }
347  }
348  }
349  }
350 
351  if (found) {
352  // Update time stamp
353  utime = (kXR_int32)time(0);
354 
355  // Rebuild hash table
356  if (Rehash(0, 0) != 0) {
357  DEBUG("problems re-hashing");
358  return 0 ;
359  }
360  }
361 
362  // We are done
363  return found;
364 }
365 
366 //__________________________________________________________________
367 bool XrdSutPFCache::Delete(XrdSutPFEntry *pfEnt)
368 {
369  struct pfQ {pfQ *next;
370  XrdSutPFEntry *pfEnt;
371  pfQ(pfQ *cP, XrdSutPFEntry *tP)
372  : next(cP), pfEnt(tP) {}
373  ~pfQ() {delete pfEnt;}
374  };
375  EPNAME("Cache::Delete");
376  static pfQ pfDefer(0,0);
377 
378 // Try to remove all deferred entries first
379 //
380  if (pfDefer.next)
381  {pfQ *pQ = &pfDefer, *dQ;
382  int nTot = 0, dTot = 0;
383  while((dQ = pQ->next))
384  {nTot++;
385  if (dQ->pfEnt->pfeMutex.CondLock())
386  {pQ->next = dQ->next;
387  dQ->pfEnt->pfeMutex.UnLock();
388  delete dQ;
389  dTot++;
390  } else pQ = dQ;
391  }
392  if (nTot) DEBUG("Deferred delete " <<dTot <<" of " <<nTot);
393  }
394 
395 // Now try to delete this entry
396 //
397  if (pfEnt->pfeMutex.CondLock())
398  {pfEnt->pfeMutex.UnLock();
399  delete pfEnt;
400  return true;
401  }
402 
403 // Defer the delete as someone still has a reference to the entry
404 //
405  pfDefer.next = new pfQ(pfDefer.next, pfEnt);
406  return false;
407 }
408 
409 //__________________________________________________________________
410 int XrdSutPFCache::Trim(int lifet)
411 {
412  // Remove entries older then lifet seconds. If lifet <=0, compare
413  // to lifetime, which can be set with SetValidity().
414  // Return number of entries removed
415 
416  // Lock for writing
417  EPNAME("Cache::Trim");
418  XrdSysRWLockHelper isg(rwlock, 0);
419 
420  //
421  // Make sure lifet makes sense; if not, use internal default
422  lifet = (lifet > 0) ? lifet : lifetime;
423 
424  //
425  // Reference time
426  int reftime = time(0) - lifet;
427 
428  // Loop over entries
429  int i = cachemx, nrm = 0;
430  for (; i >= 0; i--) {
431  if (cachent[i] && cachent[i]->mtime < reftime) {
432  if (!Delete(cachent[i]))
433  DEBUG("Delete deferred for " <<cachent[i]->name);
434  cachent[i] = 0;
435  nrm++;
436  }
437  if (i == cachemx) {
438  if (!cachent[i])
439  cachemx--;
440  }
441  }
442 
443  // We are done
444  return nrm;
445 }
446 
447 //__________________________________________________________________
448 int XrdSutPFCache::Reset(int newsz, bool lock)
449 {
450  // Remove all existing entries.
451  // If newsz > -1, set new capacity to newsz, reallocating if needed
452  // Return 0 if ok, -1 if problems reallocating.
453  EPNAME("Cache::Reset");
454 
455  // Lock for writing
456  if (lock) rwlock.WriteLock();
457 
458  // Loop over entries
459  int i = cachemx;
460  for (; i >= 0; i--) {
461  if (cachent[i]) {
462  if (!Delete(cachent[i]))
463  DEBUG("Delete deferred for " <<cachent[i]->name);
464  cachent[i] = 0;
465  }
466  }
467 
468  int rc = 0;
469  // Reallocate, if requested
470  if (newsz > -1 && newsz != cachesz) {
471  delete[] cachent;
472  cachent = 0;
473  cachesz = 0;
474  cachemx = -1;
475  isinit = 0;
476  rc = Init(newsz, 0);
477  }
478 
479  // Unlock
480  if (lock) rwlock.UnLock();
481 
482  // We are done
483  return rc;
484 }
485 
486 //________________________________________________________________
487 void XrdSutPFCache::Dump(const char *msg)
488 {
489  // Dump content of the cache
490  EPNAME("Cache::Dump");
491 
492  PRINT("//-----------------------------------------------------");
493  PRINT("//");
494  if (msg && strlen(msg) > 0) {
495  PRINT("// "<<msg);
496  PRINT("//");
497  }
498  PRINT("// Capacity: "<<cachesz);
499  PRINT("// Max index filled: "<<cachemx);
500  PRINT("//");
501 
502  // Lock for reading
503  XrdSysRWLockHelper isg(rwlock, 1);
504 
505  if (cachesz > 0) {
506 
507  XrdSutPFEntry *ent = 0;
508  int i = 0, nn = 0;
509  for (; i <= cachemx; i++) {
510 
511  // get entry
512  if ((ent = cachent[i])) {
513 
514  char smt[20] = {0};
515  XrdSutTimeString(ent->mtime,smt);
516 
517  nn++;
518  PRINT("// #:"<<nn<<" st:"<<ent->status<<" cn:"<<ent->cnt
519  <<" buf:"<<ent->buf1.len<<","<<ent->buf2.len<<","
520  <<ent->buf3.len<<","<<ent->buf4.len<<" mod:"<<smt
521  <<" name:"<<ent->name);
522  }
523 
524  }
525  PRINT("//");
526  }
527  PRINT("//-----------------------------------------------------");
528 }
529 
530 //__________________________________________________________________
531 int XrdSutPFCache::Load(const char *pfn)
532 {
533  // Initialize the cache from the content of a file of PF entries
534  // Return 0 if ok, -1 otherwise
535  EPNAME("Cache::Load");
536 
537  // Make sure file name is defined
538  if (!pfn) {
539  DEBUG("invalid input file name");
540  return -1;
541  }
542 
543  // Check if file exists and if it has been modified since last load
544  struct stat st;
545  if (stat(pfn,&st) == -1) {
546  DEBUG("cannot stat file (errno: "<<errno<<")");
547  return -1;
548  }
549  if (utime > -1 && utime > st.st_mtime) {
550  DEBUG("cached information for file "<<pfn<<" is up-to-date");
551  return 0;
552  }
553 
554  // Lock for writing
555  XrdSysRWLockHelper isg(rwlock, 0);
556 
557  // Attach to file and open it
558  XrdSutPFile ff(pfn, kPFEopen);
559  if (!ff.IsValid()) {
560  DEBUG("file is not a valid PFEntry file ("<<ff.LastErrStr()<<")");
561  return -1;
562  }
563 
564  // Read the header
565  XrdSutPFHeader header;
566  if (ff.ReadHeader(header) < 0) {
567  ff.Close();
568  return -1;
569  }
570 
571  // If the file has no entries there is nothing to do
572  if (header.entries <= 0) {
573  DEBUG("PFEntry file is empty - default init and return");
574  // Save file name
575  pfile = pfn;
576  Init(-1, 0);
577  return 0;
578  }
579 
580  // Allocate cache, if not done already or if too small
581  if (Reset(header.entries, 0) == -1) {
582  DEBUG("problems allocating / resizing cache ");
583  ff.Close();
584  return -1;
585  }
586 
587  // Read entries
588  kXR_int32 ne = 0;
589  XrdSutPFEntInd ind;
590  kXR_int32 nxtofs = header.indofs;
591  while (nxtofs > 0 && ne < header.entries) {
592  //
593  // read index entry
594  if (ff.ReadInd(nxtofs, ind) < 0) {
595  DEBUG("problems reading index entry ");
596  ff.Close();
597  return -1;
598  }
599 
600  // If active ...
601  if (ind.entofs > 0) {
602 
603  // Read entry out
604  XrdSutPFEntry ent;
605  if (ff.ReadEnt(ind.entofs, ent) < 0) {
606  ff.Close();
607  return -1;
608  }
609 
610  // Copy for the cache
611  XrdSutPFEntry *cent = new XrdSutPFEntry(ent);
612 
613  if (cent) {
614  // Set the id
615  cent->SetName(ind.name);
616 
617  // Fill the array
618  cachent[ne] = cent;
619 
620  // Count
621  ne++;
622 
623  } else {
624  DEBUG("problems duplicating entry for cache");
625  ff.Close();
626  return -1;
627  }
628  }
629 
630  // Go to next
631  nxtofs = ind.nxtofs;
632  }
633  cachemx = ne-1;
634  if (nxtofs > 0)
635  DEBUG("WARNING: inconsistent number of entries: possible file corruption");
636 
637  // Update the time stamp
638  utime = (kXR_int32)time(0);
639 
640  // Save file name
641  pfile = pfn;
642 
643  // Close the file
644  ff.Close();
645 
646  DEBUG("PF file "<<pfn<<" loaded in cache (found "<<ne<<" entries)");
647 
648  // Force update hash table
649  if (Rehash(1, 0) != 0) {
650  DEBUG("problems creating hash table");
651  return -1;
652  }
653 
654  return 0;
655 }
656 
657 
658 //__________________________________________________________________
659 int XrdSutPFCache::Rehash(bool force, bool lock)
660 {
661  // Update or create hahs table corresponding to the present content of the
662  // cache
663  // Return 0 if ok, -1 otherwise
664  EPNAME("Cache::Rehash");
665 
666  // Lock for writing
667  if (lock) rwlock.WriteLock();
668 
669  if (htmtime >= utime && !force) {
670  TRACE(Dump, "hash table is up-to-date");
671  if (lock) rwlock.UnLock();
672  return 0;
673  }
674 
675  // Clean up the hash table
676  hashtable.Purge();
677 
678  kXR_int32 i = 0, nht = 0;
679  for (; i <= cachemx; i++) {
680  if (cachent[i]) {
681  // Fill the hash table
682  kXR_int32 *key = new kXR_int32(i);
683  if (key) {
684  TRACE(Dump, "Adding ID: "<<cachent[i]->name<<"; key: "<<*key);
685  hashtable.Add(cachent[i]->name,key);
686  nht++;
687  }
688  }
689  }
690  // Update modification time
691  htmtime = (kXR_int32)time(0);
692 
693  // Unlock
694  if (lock) rwlock.UnLock();
695 
696  DEBUG("Hash table updated (found "<<nht<<" active entries)");
697  return 0;
698 }
699 
700 //__________________________________________________________________
701 int XrdSutPFCache::Flush(const char *pfn)
702 {
703  // Flush cache content to file pfn.
704  // If pfn == 0 and the cache was initialized from a file, flush
705  // to initializing file.
706  // If pfn does not exist, create it.
707  // Return 0 if ok, -1 otherwise
708  EPNAME("Cache::Flush");
709 
710  // Make sure we have all the info
711  if (!pfn && pfile.length() <= 0) {
712  DEBUG("invalid input");
713  return -1;
714  }
715  if (!pfn)
716  pfn = pfile.c_str();
717 
718  // Attach to file and open it; create if not ther
719  XrdSutPFile ff(pfn, (kPFEopen | kPFEcreate));
720  if (!ff.IsValid()) {
721  DEBUG("cannot attach-to or create file "<<pfn<<" ("<<ff.LastErrStr()<<")");
722  return -1;
723  }
724 
725  // Lock for writing
726  XrdSysRWLockHelper isg(rwlock, 0);
727 
728  //
729  // Loop over cache entries
730  int i = 0, nr = 0, nfs = 0;
731  for (; i <= cachemx; i++ ) {
732  if (cachent[i]) {
733  //
734  // Retrieve related from file, if any
735  // Read entry out
736  XrdSutPFEntry ent;
737  if ((nr = ff.ReadEntry(cachent[i]->name, ent)) < 0) {
738  ff.Close();
739  return -1;
740  }
741  //
742  // Write (update) only if older that cache or not found
743  if (nr == 0 || cachent[i]->mtime > ent.mtime) {
744  if (ff.WriteEntry(*cachent[i]) < 0) {
745  ff.Close();
746  return -1;
747  }
748  nfs++;
749  }
750  }
751  }
752 
753  // Close the file
754  ff.Close();
755 
756  // Update the time stamp (to avoid fake loads later on)
757  utime = (kXR_int32)time(0);
758 
759  // Save file name
760  if (pfile.length() <= 0)
761  pfile = pfn;
762 
763  DEBUG("Cache flushed to file "<<pfn<<" ("<<nfs<<" entries updated / written)");
764 
765  return 0;
766 }
767 
768 //__________________________________________________________________
770 {
771  // Refresh content of a cache created from file.
772  // Return 0 if ok, -1 otherwise
773  EPNAME("Cache::Refresh");
774 
775  // Make sure we have all the info
776  if (pfile.length() <= 0) {
777  DEBUG("cache was not initialized from file - do nothing");
778  return -1;
779  }
780 
781  // Check if file exists and if it has been modified since last load
782  struct stat st;
783  if (stat(pfile.c_str(),&st) == -1) {
784  DEBUG("cannot stat file (errno: "<<errno<<")");
785  return -1;
786  }
787  if (utime > -1 && utime > st.st_mtime) {
788  DEBUG("cached information for file "<<pfile<<" is up-to-date");
789  return 0;
790  }
791 
792  // Lock for writing
793  XrdSysRWLockHelper isg(rwlock, 0);
794 
795  if (Load(pfile.c_str()) != 0) {
796  DEBUG("problems loading passwd information from file: "<<pfile);
797  return -1;
798  }
799 
800  // Update the time stamp (to avoid fake loads or refreshs later on)
801  utime = (kXR_int32)time(0);
802 
803  DEBUG("Cache refreshed from file: "<<pfile);
804 
805  return 0;
806 }
807 
808 
int kXR_int32
Definition: XPtypes.hh:89
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define PRINT(y)
int stat(const char *path, struct stat *buf)
int XrdSutTimeString(int t, char *st, int opt)
Definition: XrdSutAux.cc:311
#define kPFEopen
Definition: XrdSutPFile.hh:60
#define kPFEcreate
Definition: XrdSutPFile.hh:59
#define TRACE(act, x)
Definition: XrdTrace.hh:63
#define ID
void Purge()
Definition: XrdOucHash.icc:193
T * Add(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default)
Definition: XrdOucHash.icc:61
T * Find(const char *KeyVal, time_t *KeyTime=0)
Definition: XrdOucHash.icc:160
const char * c_str() const
int length() const
kXR_int32 len
void Lock(XrdSysMutex *Mutex)
void Set(XrdSysMutex *Mutex)
virtual ~XrdSutPFCache()
bool Remove(const char *ID, int opt=1)
int Flush(const char *pfname=0)
XrdSutPFEntry * Add(XrdSutPFCacheRef &urRef, const char *ID, bool force=0)
int Reset(int newsz=-1, bool lock=1)
int Init(int capacity=100, bool lock=1)
void Dump(const char *msg=0)
int Load(const char *pfname)
int Rehash(bool force=0, bool lock=1)
int Trim(int lifet=0)
kXR_int32 entofs
Definition: XrdSutPFile.hh:88
kXR_int32 nxtofs
Definition: XrdSutPFile.hh:87
kXR_int32 mtime
XrdSutPFBuf buf3
XrdSutPFBuf buf1
XrdSysMutex pfeMutex
void SetName(const char *n=0)
XrdSutPFBuf buf2
XrdSutPFBuf buf4
kXR_int32 entries
Definition: XrdSutPFile.hh:108
kXR_int32 indofs
Definition: XrdSutPFile.hh:109
kXR_int32 WriteEntry(XrdSutPFEntry ent)
Definition: XrdSutPFile.cc:585
bool IsValid() const
Definition: XrdSutPFile.hh:170
const char * LastErrStr() const
Definition: XrdSutPFile.hh:173
kXR_int32 Close(kXR_int32 d=-1)
Definition: XrdSutPFile.cc:450
kXR_int32 ReadEntry(const char *name, XrdSutPFEntry &ent, int opt=0)
Definition: XrdSutPFile.cc:909
void Lock(XrdSysRWLock *lock, bool rd=1)
static void Wait(int milliseconds)
Definition: XrdSysTimer.cc:227