XRootD
XrdSutPFile.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S u t P F i l e . c c */
4 /* */
5 /* (c) 2012 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 <cstring>
31 #include <unistd.h>
32 #include <cstdlib>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <ctime>
37 
38 #include "XrdSut/XrdSutAux.hh"
39 #include "XrdSut/XrdSutPFEntry.hh"
40 #include "XrdSut/XrdSutPFile.hh"
41 #include "XrdSut/XrdSutTrace.hh"
42 #include "XrdSys/XrdSysE2T.hh"
43 
44 //_________________________________________________________________
46  kXR_int32 eo, kXR_int32 es)
47 {
48  // Constructor
49 
50  name = 0;
51  if (n) {
52  name = new char[strlen(n)+1];
53  if (name)
54  strcpy(name,n);
55  }
56  nxtofs = no;
57  entofs = eo;
58  entsiz = es;
59 }
60 
61 //_________________________________________________________________
63 {
64  //Copy constructor
65 
66  name = 0;
67  if (ei.name) {
68  name = new char[strlen(ei.name)+1];
69  if (name)
70  strcpy(name,ei.name);
71  }
72  nxtofs = ei.nxtofs;
73  entofs = ei.entofs;
74  entsiz = ei.entsiz;
75 }
76 
77 //_________________________________________________________________
78 void XrdSutPFEntInd::SetName(const char *n)
79 {
80  // Name setter
81 
82  if (name) {
83  delete[] name;
84  name = 0;
85  }
86  if (n) {
87  name = new char[strlen(n)+1];
88  if (name)
89  strcpy(name,n);
90  }
91 }
92 
93 //______________________________________________________________________________
95 {
96  // Assign index entry ei to local index entry.
97 
98  name = 0;
99  if (ei.name) {
100  name = new char[strlen(ei.name)+1];
101  if (name)
102  strcpy(name,ei.name);
103  }
104  nxtofs = ei.nxtofs;
105  entofs = ei.entofs;
106  entsiz = ei.entsiz;
107 
108  return *this;
109 }
110 
111 //_________________________________________________________________
113  kXR_int32 it, kXR_int32 ent, kXR_int32 ofs)
114 {
115  // Constructor
116 
117  memset(fileID,0,kFileIDSize);
118  if (id) {
119  kXR_int32 lid = strlen(id);
120  if (lid > kFileIDSize)
121  lid = kFileIDSize;
122  memcpy(fileID,id,lid);
123  }
124  version = v;
125  ctime = ct;
126  itime = it;
127  entries = ent;
128  indofs = ofs;
129  jnksiz = 0; // At start everything is reachable
130 }
131 
132 //_________________________________________________________________
134 {
135  // Copy constructor
136 
137  memcpy(fileID,fh.fileID,kFileIDSize);
138  version = fh.version;
139  ctime = fh.ctime;
140  itime = fh.itime;
141  entries = fh.entries;
142  indofs = fh.indofs;
143  jnksiz = fh.jnksiz;
144 }
145 
146 //_________________________________________________________________
148 {
149  // Header printout
150 
151  struct tm tst;
152 
153  // String form for time of last change
154  char sctime[256] = {0};
155  time_t ttmp = ctime;
156  localtime_r(&ttmp,&tst);
157  asctime_r(&tst,sctime);
158  sctime[strlen(sctime)-1] = 0;
159 
160  // String form for time of last index change
161  char sitime[256] = {0};
162  ttmp = itime;
163  localtime_r(&ttmp,&tst);
164  asctime_r(&tst,sitime);
165  sitime[strlen(sitime)-1] = 0;
166 
167  fprintf(stdout,
168  "//------------------------------------"
169  "------------------------------//\n"
170  "// \n"
171  "// File Header dump \n"
172  "// \n"
173  "// File ID: %s \n"
174  "// version: %d \n"
175  "// last changed on: %s (%d sec) \n"
176  "// index changed on: %s (%d sec) \n"
177  "// entries: %d \n"
178  "// unreachable: %d \n"
179  "// first ofs: %d \n"
180  "// \n"
181  "//------------------------------------"
182  "------------------------------//\n",
183  fileID,version,sctime,ctime,sitime,itime,entries,jnksiz,indofs);
184 }
185 
186 //________________________________________________________________
187 XrdSutPFile::XrdSutPFile(const char *n, kXR_int32 openmode,
188  kXR_int32 createmode, bool hashtab)
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 }
205 
206 //________________________________________________________________
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 }
219 
220 //________________________________________________________________
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 }
234 
235 //________________________________________________________________
236 bool XrdSutPFile::Init(const char *n, kXR_int32 openmode,
237  kXR_int32 createmode, bool hashtab)
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 }
298 
299 //_________________________________________________________________
301  const char *nam, kXR_int32 createmode)
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 }
448 
449 //_________________________________________________________________
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 }
482 
483 //_________________________________________________________________
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 }
501 
502 //_________________________________________________________________
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 }
521 
522 //_________________________________________________________________
523 kXR_int32 XrdSutPFile::WriteHeader(XrdSutPFHeader hd)
524 {
525  // Write/Update header to beginning of opne stream
526 
527  //
528  // Build output buffer
529  // Get total lenght needed
530  kXR_int32 ltot = hd.Length();
531  //
532  // Allocate the buffer
533  char *bout = new char[ltot];
534  if (!bout)
535  return Err(kPFErrOutOfMemory,"WriteHeader");
536  //
537  // Fill the buffer
538  kXR_int32 lp = 0;
539  // File ID
540  memcpy(bout+lp,hd.fileID,kFileIDSize);
541  lp += kFileIDSize;
542  // version
543  memcpy(bout+lp,&hd.version,sizeof(kXR_int32));
544  lp += sizeof(kXR_int32);
545  // change time
546  memcpy(bout+lp,&hd.ctime,sizeof(kXR_int32));
547  lp += sizeof(kXR_int32);
548  // index change time
549  memcpy(bout+lp,&hd.itime,sizeof(kXR_int32));
550  lp += sizeof(kXR_int32);
551  // entries
552  memcpy(bout+lp,&hd.entries,sizeof(kXR_int32));
553  lp += sizeof(kXR_int32);
554  // offset of the first index entry
555  memcpy(bout+lp,&hd.indofs,sizeof(kXR_int32));
556  lp += sizeof(kXR_int32);
557  // number of unused bytes
558  memcpy(bout+lp,&hd.jnksiz,sizeof(kXR_int32));
559  lp += sizeof(kXR_int32);
560  // Check length
561  if (lp != ltot) {
562  if (bout) delete[] bout;
563  return Err(kPFErrLenMismatch,"WriteHeader",
564  (const char *)&lp, (const char *)&ltot);
565  }
566  //
567  // Ready to write: check we got the file
568  if (fFd < 0)
569  return Err(kPFErrFileNotOpen,"WriteHeader");
570  //
571  // Set the offset
572  if (lseek(fFd, 0, SEEK_SET) == -1) {
573  return Err(kPFErrSeek,"WriteHeader","SEEK_SET",(const char *)&fFd);
574  }
575 
576  kXR_int32 nw = 0;
577  // Now write the buffer to the stream
578  while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
579  errno = 0;
580 
581  return nw;
582 }
583 
584 //______________________________________________________________________
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 }
793 
794 //________________________________________________________________
795 kXR_int32 XrdSutPFile::UpdateCount(const char *tag, int *cnt,
796  int step, bool reset)
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 }
907 
908 //________________________________________________________________
910  XrdSutPFEntry &ent, int opt)
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 }
1040 
1041 //________________________________________________________________
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 }
1078 
1079 //________________________________________________________________
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 }
1191 
1192 //________________________________________________________________
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 }
1267 
1268 //_________________________________________________________________
1269 kXR_int32 XrdSutPFile::Reset(kXR_int32 ofs, kXR_int32 siz)
1270 {
1271  // Reset size bytes starting at ofs in the open stream
1272 
1273  //
1274  // Set the offset
1275  if (lseek(fFd, ofs, SEEK_SET) == -1)
1276  return Err(kPFErrSeek,"Reset",
1277  "SEEK_SET",(const char *)&fFd);
1278 
1279  kXR_int32 nrs = 0;
1280  // Now write the buffer to the stream
1281  while (nrs < siz) {
1282  char c = 0;
1283  while (write(fFd, &c, 1) < 0 && errno == EINTR)
1284  errno = 0;
1285  nrs++;
1286  }
1287 
1288  return nrs;
1289 }
1290 
1291 
1292 //__________________________________________________________________
1293 kXR_int32 XrdSutPFile::WriteInd(kXR_int32 ofs, XrdSutPFEntInd ind)
1294 {
1295  // Write entry index to open stream fFd
1296 
1297  // Make sure we got an open stream
1298  if (fFd < 0)
1299  return Err(kPFErrFileNotOpen,"WriteInd");
1300  //
1301  // Set the offset
1302  if (lseek(fFd, ofs, SEEK_SET) == -1)
1303  return Err(kPFErrSeek,"WriteInd",
1304  "SEEK_SET",(const char *)&fFd);
1305  //
1306  // Build output buffer
1307  //
1308  // Get total lenght needed
1309  kXR_int32 ltot = ind.Length();
1310  //
1311  // Allocate the buffer
1312  char *bout = new char[ltot];
1313  if (!bout)
1314  return Err(kPFErrOutOfMemory,"WriteInd");
1315  //
1316  // Fill the buffer
1317  kXR_int32 lp = 0;
1318  // Name length
1319  kXR_int32 lnam = strlen(ind.name);
1320  memcpy(bout+lp,&lnam,sizeof(kXR_int32));
1321  lp += sizeof(kXR_int32);
1322  // Offset of next index entry
1323  memcpy(bout+lp,&ind.nxtofs,sizeof(kXR_int32));
1324  lp += sizeof(kXR_int32);
1325  // Offset of entry
1326  memcpy(bout+lp,&ind.entofs,sizeof(kXR_int32));
1327  lp += sizeof(kXR_int32);
1328  // Size allocated for entry
1329  memcpy(bout+lp,&ind.entsiz,sizeof(kXR_int32));
1330  lp += sizeof(kXR_int32);
1331  // name
1332  memcpy(bout+lp,ind.name,lnam);
1333  lp += lnam;
1334  // Check length
1335  if (lp != ltot) {
1336  if (bout) delete[] bout;
1337  return Err(kPFErrLenMismatch,"WriteInd",
1338  (const char *)&lp, (const char *)&ltot);
1339  }
1340 
1341  kXR_int32 nw = 0;
1342  // Now write the buffer to the stream
1343  while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
1344  errno = 0;
1345 
1346  return nw;
1347 }
1348 
1349 //__________________________________________________________________
1350 kXR_int32 XrdSutPFile::WriteEnt(kXR_int32 ofs, XrdSutPFEntry ent)
1351 {
1352  // Write ent to stream out
1353 
1354  // Make sure we got an open stream
1355  if (fFd < 0)
1356  return Err(kPFErrFileNotOpen,"WriteEnt");
1357  //
1358  // Set the offset
1359  if (lseek(fFd, ofs, SEEK_SET) == -1)
1360  return Err(kPFErrSeek,"WriteEnt",
1361  "SEEK_SET",(const char *)&fFd);
1362  //
1363  // Build output buffer
1364  //
1365  // Get total lenght needed
1366  kXR_int32 ltot = ent.Length();
1367  //
1368  // Allocate the buffer
1369  char *bout = new char[ltot];
1370  if (!bout)
1371  return Err(kPFErrOutOfMemory,"WriteEnt");
1372  //
1373  // Fill the buffer
1374  kXR_int32 lp = 0;
1375  // status
1376  memcpy(bout+lp,&ent.status,sizeof(short));
1377  lp += sizeof(short);
1378  // count
1379  memcpy(bout+lp,&ent.cnt,sizeof(short));
1380  lp += sizeof(short);
1381  // time of modification / creation
1382  memcpy(bout+lp,&ent.mtime,sizeof(kXR_int32));
1383  lp += sizeof(kXR_int32);
1384  // length of first buffer
1385  memcpy(bout+lp,&ent.buf1.len,sizeof(kXR_int32));
1386  lp += sizeof(kXR_int32);
1387  // length of second buffer
1388  memcpy(bout+lp,&ent.buf2.len,sizeof(kXR_int32));
1389  lp += sizeof(kXR_int32);
1390  // length of third buffer
1391  memcpy(bout+lp,&ent.buf3.len,sizeof(kXR_int32));
1392  lp += sizeof(kXR_int32);
1393  // length of fourth buffer
1394  memcpy(bout+lp,&ent.buf4.len,sizeof(kXR_int32));
1395  lp += sizeof(kXR_int32);
1396  if (ent.buf1.len > 0) {
1397  // first buffer
1398  memcpy(bout+lp,ent.buf1.buf,ent.buf1.len);
1399  lp += ent.buf1.len;
1400  }
1401  if (ent.buf2.len > 0) {
1402  // second buffer
1403  memcpy(bout+lp,ent.buf2.buf,ent.buf2.len);
1404  lp += ent.buf2.len;
1405  }
1406  if (ent.buf3.len > 0) {
1407  // third buffer
1408  memcpy(bout+lp,ent.buf3.buf,ent.buf3.len);
1409  lp += ent.buf3.len;
1410  }
1411  if (ent.buf4.len > 0) {
1412  // third buffer
1413  memcpy(bout+lp,ent.buf4.buf,ent.buf4.len);
1414  lp += ent.buf4.len;
1415  }
1416  // Check length
1417  if (lp != ltot) {
1418  if (bout) delete[] bout;
1419  return Err(kPFErrLenMismatch,"WriteEnt",
1420  (const char *)&lp, (const char *)&ltot);
1421  }
1422 
1423  kXR_int32 nw = 0;
1424  // Now write the buffer to the stream
1425  while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
1426  errno = 0;
1427 
1428  return nw;
1429 }
1430 
1431 //__________________________________________________________________
1432 kXR_int32 XrdSutPFile::ReadHeader(XrdSutPFHeader &hd)
1433 {
1434  // Read header from beginning of stream
1435 
1436  //
1437  // Make sure that we got an open file description
1438  if (fFd < 0)
1439  return Err(kPFErrFileNotOpen,"ReadHeader");
1440  //
1441  // Set the offset
1442  if (lseek(fFd, 0, SEEK_SET) == -1)
1443  return Err(kPFErrSeek,"ReadHeader",
1444  "SEEK_SET",(const char *)&fFd);
1445 
1446  kXR_int32 nr = 0, nrdt = 0;
1447  //
1448  // Now read the information step by step:
1449  // the file ID ...
1450  if ((nr = read(fFd,hd.fileID,kFileIDSize)) != kFileIDSize)
1451  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1452  hd.fileID[kFileIDSize-1] = 0;
1453  nrdt += nr;
1454  // the version ...
1455  if ((nr = read(fFd,&hd.version,sizeof(kXR_int32))) != sizeof(kXR_int32))
1456  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1457  nrdt += nr;
1458  // the time of last change ...
1459  if ((nr = read(fFd,&hd.ctime,sizeof(kXR_int32))) != sizeof(kXR_int32))
1460  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1461  nrdt += nr;
1462  // the time of last index change ...
1463  if ((nr = read(fFd,&hd.itime,sizeof(kXR_int32))) != sizeof(kXR_int32))
1464  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1465  nrdt += nr;
1466  // the number of entries ...
1467  if ((nr = read(fFd,&hd.entries,sizeof(kXR_int32))) != sizeof(kXR_int32))
1468  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1469  nrdt += nr;
1470  // the offset of first index entry ...
1471  if ((nr = read(fFd,&hd.indofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
1472  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1473  nrdt += nr;
1474  // the number of unused bytes ...
1475  if ((nr = read(fFd,&hd.jnksiz,sizeof(kXR_int32))) != sizeof(kXR_int32))
1476  return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
1477  nrdt += nr;
1478 
1479  return nrdt;
1480 }
1481 
1482 //_____________________________________________________________________
1483 kXR_int32 XrdSutPFile::ReadInd(kXR_int32 ofs, XrdSutPFEntInd &ind)
1484 {
1485  // Read entry index from offset ofs of open stream fFd
1486 
1487  //
1488  // Make sure that we got an open file description
1489  if (fFd < 0)
1490  return Err(kPFErrFileNotOpen,"ReadInd");
1491  //
1492  // Set the offset
1493  if (lseek(fFd, ofs, SEEK_SET) == -1)
1494  return Err(kPFErrSeek,"ReadInd",
1495  "SEEK_SET",(const char *)&fFd);
1496 
1497  kXR_int32 nr = 0, nrdt = 0;
1498  //
1499  // Now read the information step by step:
1500  // the length of the name ...
1501  kXR_int32 lnam = 0;
1502  if ((nr = read(fFd,&lnam,sizeof(kXR_int32))) != sizeof(kXR_int32))
1503  return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1504  nrdt += nr;
1505  // the offset of next entry index ...
1506  if ((nr = read(fFd,&ind.nxtofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
1507  return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1508  nrdt += nr;
1509  // the offset of the entry ...
1510  if ((nr = read(fFd,&ind.entofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
1511  return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1512  nrdt += nr;
1513  // the size allocated for the entry ...
1514  if ((nr = read(fFd,&ind.entsiz,sizeof(kXR_int32))) != sizeof(kXR_int32))
1515  return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1516  nrdt += nr;
1517  // the name ... cleanup first
1518  if (ind.name) {
1519  delete[] ind.name;
1520  ind.name = 0;
1521  }
1522  if (lnam) {
1523  if (lnam > 0)
1524  ind.name = new char[lnam+1];
1525  if (ind.name) {
1526  if ((nr = read(fFd,ind.name,lnam)) != lnam)
1527  return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1528  ind.name[lnam] = 0; // null-terminated
1529  nrdt += nr;
1530  } else
1531  return Err(kPFErrOutOfMemory,"ReadInd");
1532  }
1533 
1534  return nrdt;
1535 }
1536 
1537 //____________________________________________________________________
1538 kXR_int32 XrdSutPFile::ReadEnt(kXR_int32 ofs, XrdSutPFEntry &ent)
1539 {
1540  // Read ent from current position at stream
1541 
1542  //
1543  // Make sure that we got an open file description
1544  if (fFd < 0)
1545  return Err(kPFErrFileNotOpen,"ReadEnt");
1546  //
1547  // Set the offset
1548  if (lseek(fFd, ofs, SEEK_SET) == -1)
1549  return Err(kPFErrSeek,"ReadEnt",
1550  "SEEK_SET",(const char *)&fFd);
1551 
1552  kXR_int32 nr = 0, nrdt = 0;
1553  //
1554  // Now read the information step by step:
1555  // the status ...
1556  if ((nr = read(fFd,&ent.status,sizeof(short))) != sizeof(short))
1557  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1558  nrdt += nr;
1559  // the count var ...
1560  if ((nr = read(fFd,&ent.cnt,sizeof(short))) != sizeof(short))
1561  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1562  nrdt += nr;
1563  // the the time of modification / creation ...
1564  if ((nr = read(fFd,&ent.mtime,sizeof(kXR_int32))) != sizeof(kXR_int32))
1565  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1566  nrdt += nr;
1567  // the length of the first buffer ...
1568  if ((nr = read(fFd,&ent.buf1.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1569  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1570  nrdt += nr;
1571  // the length of the second buffer ...
1572  if ((nr = read(fFd,&ent.buf2.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1573  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1574  nrdt += nr;
1575  // the length of the third buffer ...
1576  if ((nr = read(fFd,&ent.buf3.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1577  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1578  nrdt += nr;
1579  // the length of the fourth buffer ...
1580  if ((nr = read(fFd,&ent.buf4.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1581  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1582  nrdt += nr;
1583  // Allocate space for the first buffer and read it (if any) ...
1584  if (ent.buf1.len) {
1585  ent.buf1.buf = new char[ent.buf1.len];
1586  if (!ent.buf1.buf)
1587  return Err(kPFErrOutOfMemory,"ReadEnt");
1588  if ((nr = read(fFd,ent.buf1.buf,ent.buf1.len)) != ent.buf1.len)
1589  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1590  nrdt += nr;
1591  }
1592  // Allocate space for the second buffer and read it (if any) ...
1593  if (ent.buf2.len) {
1594  ent.buf2.buf = new char[ent.buf2.len];
1595  if (!ent.buf2.buf)
1596  return Err(kPFErrOutOfMemory,"ReadEnt");
1597  if ((nr = read(fFd,ent.buf2.buf,ent.buf2.len)) != ent.buf2.len)
1598  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1599  nrdt += nr;
1600  }
1601  // Allocate space for the third buffer and read it (if any) ...
1602  if (ent.buf3.len) {
1603  ent.buf3.buf = new char[ent.buf3.len];
1604  if (!ent.buf3.buf)
1605  return Err(kPFErrOutOfMemory,"ReadEnt");
1606  if ((nr = read(fFd,ent.buf3.buf,ent.buf3.len)) != ent.buf3.len)
1607  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1608  nrdt += nr;
1609  }
1610  // Allocate space for the fourth buffer and read it (if any) ...
1611  if (ent.buf4.len) {
1612  ent.buf4.buf = new char[ent.buf4.len];
1613  if (!ent.buf4.buf)
1614  return Err(kPFErrOutOfMemory,"ReadEnt");
1615  if ((nr = read(fFd,ent.buf4.buf,ent.buf4.len)) != ent.buf4.len)
1616  return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1617  nrdt += nr;
1618  }
1619 
1620  return nrdt;
1621 }
1622 
1623 //________________________________________________________________
1625 {
1626  // Display the content of the file
1627 
1628  // Make sure we got an open stream
1629  if (Open(1) < 0)
1630  return -1;
1631 
1632  // Read header
1633  XrdSutPFHeader hdr;
1634  if (ReadHeader(hdr) < 0) {
1635  Close();
1636  return -1;
1637  }
1638 
1639  // Time strings
1640  struct tm tst;
1641  char sctime[256] = {0};
1642  time_t ttmp = hdr.ctime;
1643  localtime_r(&ttmp,&tst);
1644  asctime_r(&tst,sctime);
1645  sctime[strlen(sctime)-1] = 0;
1646  char sitime[256] = {0};
1647  ttmp = hdr.itime;
1648  localtime_r(&ttmp,&tst);
1649  asctime_r(&tst,sitime);
1650  sitime[strlen(sitime)-1] = 0;
1651 
1652  // Default is stdout
1653  FILE *out = oout ? (FILE *)oout : stdout;
1654 
1655  fprintf(out,"//-----------------------------------------------------"
1656  "--------------------//\n");
1657  fprintf(out,"//\n");
1658  fprintf(out,"// File: %s\n",name);
1659  fprintf(out,"// ID: %s\n",hdr.fileID);
1660  fprintf(out,"// Version: %d\n",hdr.version);
1661  fprintf(out,"// Last change : %s (%d sec)\n",sctime,hdr.ctime);
1662  fprintf(out,"// Index change: %s (%d sec)\n",sitime,hdr.itime);
1663  fprintf(out,"//\n");
1664  fprintf(out,"// Number of Entries: %d\n",hdr.entries);
1665  fprintf(out,"// Bytes unreachable: %d\n",hdr.jnksiz);
1666  fprintf(out,"//\n");
1667 
1668  if (hdr.entries > 0) {
1669 
1670  // Special entries first, if any
1672  if (ns > 0) {
1673  // Allocate space for offsets
1674  kXR_int32 *sofs = new kXR_int32[ns];
1675  if (sofs) {
1676  // Get offsets
1677  ns = SearchSpecialEntries(sofs,ns);
1678  fprintf(out,"// Special entries (%d):\n",ns);
1679  int i = 0;
1680  for (; i<ns; i++) {
1681 
1682  // Read entry index at ofs
1683  XrdSutPFEntInd ind;
1684  if (ReadInd(sofs[i], ind) < 0) {
1685  Close();
1686  return -1;
1687  }
1688 
1689  if (ind.entofs) {
1690  // Read entry
1691  XrdSutPFEntry ent;
1692  if (ReadEnt(ind.entofs, ent) < 0) {
1693  Close();
1694  return -1;
1695  }
1696  char smt[20] = {0};
1697  XrdSutTimeString(ent.mtime,smt);
1698  std::string buffer;
1699  char buf[2048] = {0};
1700  memset(buf,0,2048);
1701  sprintf(buf,"// #%d mod:%s",i+1,smt);
1702  buffer = buf;
1703  sprintf(buf," name:%s",ind.name);
1704  buffer += buf;
1705  fprintf(out,"%s\n",buffer.c_str());
1706 
1707  buffer.clear();
1708  sprintf(buf,"// buf");
1709  buffer = buf;
1710 
1711  if (ent.cnt == 1) {
1712  if (ent.buf1.len && ent.buf1.buf)
1713  {
1714  sprintf(buf,": %.*s",ent.buf1.len,ent.buf1.buf);
1715  buffer += buf;
1716  }
1717  if (ent.buf2.len && ent.buf2.buf)
1718  {
1719  sprintf(buf,": %.*s",ent.buf2.len,ent.buf2.buf);
1720  buffer += buf;
1721  }
1722  if (ent.buf3.len && ent.buf3.buf)
1723  {
1724  sprintf(buf,": %.*s",ent.buf3.len,ent.buf3.buf);
1725  buffer += buf;
1726  }
1727  if (ent.buf4.len && ent.buf4.buf)
1728  {
1729  sprintf(buf,": %.*s",ent.buf4.len,ent.buf4.buf);
1730  buffer += buf;
1731  }
1732  } else {
1733  sprintf(buf,":%d:%d:%d:%d",
1734  ent.buf1.len,ent.buf2.len,ent.buf3.len,
1735  ent.buf4.len);
1736  buffer += buf;
1737  buffer += " (protected)";
1738  }
1739  fprintf(out,"%s\n",buf);
1740  }
1741  }
1742  fprintf(out,"//\n");
1743  delete[] sofs;
1744  }
1745  }
1746 
1747  if (hdr.entries > ns)
1748  fprintf(out,"// Normal entries (%d):\n",hdr.entries-ns);
1749 
1750  kXR_int32 nn = 0;
1751  kXR_int32 nxtofs = hdr.indofs;
1752  while (nxtofs) {
1753 
1754  // Read entry index at ofs
1755  XrdSutPFEntInd ind;
1756  if (ReadInd(nxtofs, ind) < 0) {
1757  Close();
1758  return -3;
1759  }
1760 
1761  if (ind.entofs) {
1762  // Read entry
1763  XrdSutPFEntry ent;
1764  if (ReadEnt(ind.entofs, ent) < 0) {
1765  Close();
1766  return -4;
1767  }
1768  if (ent.status != kPFE_special) {
1769  char smt[20] = {0};
1770  XrdSutTimeString(ent.mtime,smt);
1771 
1772  nn++;
1773  fprintf(out,
1774  "// #:%d st:%d cn:%d buf:%d,%d,%d,%d mod:%s name:%s\n",
1775  nn,ent.status,ent.cnt,ent.buf1.len,ent.buf2.len,ent.buf3.len,
1776  ent.buf4.len,smt,ind.name);
1777  }
1778  }
1779 
1780  // Read next
1781  nxtofs = ind.nxtofs;
1782  }
1783  fprintf(out,"//\n");
1784  }
1785  fprintf(out,"//-----------------------------------------------------"
1786  "--------------------//\n");
1787 
1788  // Close the file
1789  Close();
1790 
1791  return 0;
1792 }
1793 
1794 //________________________________________________________________
1795 kXR_int32 XrdSutPFile::Trim(const char *fbak)
1796 {
1797  // Trim away unreachable entries from the file
1798  // Previous content is save in a file name fbak, the default
1799  // being 'name'.bak
1800  EPNAME("PFile::Trim");
1801 
1802  // Retrieve header, first, to check if there is anything to trim
1803  XrdSutPFHeader header;
1804  if (RetrieveHeader(header) < 0)
1805  return -1;
1806  if (header.jnksiz <= 0) {
1807  DEBUG("nothing to trim - return ");
1808  return -1;
1809  }
1810 
1811  // Get name of backup file
1812  char *nbak = (char *)fbak;
1813  if (!nbak) {
1814  // Use default
1815  nbak = new char[strlen(name)+5];
1816  if (!nbak)
1817  return Err(kPFErrOutOfMemory,"Trim");
1818  sprintf(nbak,"%s.bak",name);
1819  DEBUG("backup file: "<<nbak);
1820  }
1821 
1822  // Move file
1823  if (rename(name,nbak) == -1)
1824  return Err(kPFErrFileRename,"Trim",name,nbak);
1825 
1826  // Create new file
1827  int fdnew = Open(1);
1828  if (fdnew < 0)
1829  return -1;
1830 
1831  // Open backup file
1832  int fdbck = Open(1,0,nbak);
1833  if (fdbck < 0) {
1834  Close();
1835  return -1;
1836  }
1837 
1838  // Read the header from backup file
1839  fFd = fdbck;
1840  if (ReadHeader(header) < 0) {
1841  Close(fdnew); Close(fdbck);
1842  return -1;
1843  }
1844 
1845  // Copy it to new file
1846  fFd = fdnew;
1847  if (WriteHeader(header) < 0) {
1848  Close(fdnew); Close(fdbck);
1849  return -1;
1850  }
1851  kXR_int32 wrofs = lseek(fdnew, 0, SEEK_CUR);
1852  if (wrofs == -1) {
1853  Close(fdnew); Close(fdbck);
1854  return Err(kPFErrSeek,"Trim",
1855  "SEEK_CUR",(const char *)&fdnew);
1856  }
1857 
1858  // Read active entries now and save them to new file
1859  bool firstind = 1;
1860  XrdSutPFEntInd ind, indlast;
1861  XrdSutPFEntry ent;
1862 
1863  kXR_int32 nxtofs = header.indofs;
1864  kXR_int32 lastofs = nxtofs;
1865 
1866  while (nxtofs) {
1867 
1868  // Read index entry
1869  fFd = fdbck;
1870  if (ReadInd(nxtofs,ind) < 0) {
1871  Close(fdnew); Close(fdbck);
1872  return -1;
1873  }
1874 
1875  // Get Next index entry before updating index entry
1876  nxtofs = ind.nxtofs;
1877 
1878  // Read entry, if active
1879  if (ind.entofs > 0) {
1880  fFd = fdbck;
1881  if (ReadEnt(ind.entofs,ent) < 0) {
1882  Close(fdnew); Close(fdbck);
1883  return -1;
1884  }
1885  // Update index entry
1886  ind.entofs = wrofs;
1887 
1888  // Write active entry
1889  fFd = fdnew;
1890  if (WriteEnt(wrofs,ent) < 0) {
1891  Close(fdnew); Close(fdbck);
1892  return -1;
1893  }
1894 
1895  // Update write offset
1896  if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1897  Close(fdnew); Close(fdbck);
1898  return Err(kPFErrSeek,"Trim",
1899  "SEEK_CUR",(const char *)&fdnew);
1900  }
1901 
1902  if (firstind) {
1903  // Update header
1904  header.indofs = wrofs;
1905  firstind = 0;
1906  } else {
1907  // Update previous index entry
1908  indlast.nxtofs = wrofs;
1909  fFd = fdnew;
1910  if (WriteInd(lastofs,indlast) < 0) {
1911  Close(fdnew); Close(fdbck);
1912  return -1;
1913  }
1914  }
1915 
1916  // Save this index for later updates
1917  indlast = ind;
1918  lastofs = wrofs;
1919 
1920  // Last index entry, for now
1921  ind.nxtofs = 0;
1922 
1923  // Write active index entry
1924  fFd = fdnew;
1925  if (WriteInd(wrofs,ind) < 0) {
1926  Close(fdnew); Close(fdbck);
1927  return -1;
1928  }
1929 
1930  // Update write offset
1931  if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1932  Close(fdnew); Close(fdbck);
1933  return Err(kPFErrSeek,"Trim",
1934  "SEEK_CUR",(const char *)&fdnew);
1935  }
1936  }
1937  }
1938 
1939  // Close backup file
1940  Close(fdbck);
1941  fFd = fdnew;
1942 
1943  // Update header
1944  header.ctime = (kXR_int32)time(0);
1945  header.itime = header.ctime;
1946  header.jnksiz = 0;
1947 
1948  // Copy it to new file
1949  if (WriteHeader(header) < 0) {
1950  Close();;
1951  return -1;
1952  }
1953 
1954  // Close the file
1955  Close();
1956 
1957  return 0;
1958 }
1959 
1960 //________________________________________________________________
1961 kXR_int32 XrdSutPFile::UpdateHashTable(bool force)
1962 {
1963  // Update hash table reflecting the index of the file
1964  // If force is .true. the table is recreated even if no recent
1965  // change in the index has occurred.
1966  // Returns the number of entries in the table.
1967 
1968  // The file must be open
1969  if (fFd < 0)
1970  return Err(kPFErrFileNotOpen,"UpdateHashTable");
1971 
1972  // Read the header
1973  XrdSutPFHeader header;
1974  if (ReadHeader(header) < 0)
1975  return -1;
1976 
1977  // If no recent changes and no force option, return
1978  if (!force && header.itime < fHTutime)
1979  return 0;
1980 
1981  // Clean up the table or create it
1982  if (fHashTable)
1983  fHashTable->Purge();
1984  else
1985  fHashTable = new XrdOucHash<kXR_int32>;
1986  // Make sure we have it
1987  if (!fHashTable)
1988  return Err(kPFErrOutOfMemory,"UpdateHashTable");
1989 
1990  // Read entries
1991  kXR_int32 ne = 0;
1992  if (header.entries > 0) {
1993  XrdSutPFEntInd ind;
1994  kXR_int32 nxtofs = header.indofs;
1995  while (nxtofs > 0) {
1996  if (ReadInd(nxtofs, ind) < 0)
1997  return -1;
1998  ne++;
1999  // Fill the table
2000  kXR_int32 *key = new kXR_int32(nxtofs);
2001  fHashTable->Add(ind.name,key);
2002  // Go to next
2003  nxtofs = ind.nxtofs;
2004  }
2005  }
2006 
2007  // Update the time stamp
2008  fHTutime = (kXR_int32)time(0);
2009 
2010  return ne;
2011 }
2012 
2013 //________________________________________________________________
2014 kXR_int32 XrdSutPFile::RemoveEntries(const char *tag, char opt)
2015 {
2016  // Remove entries whose tag is compatible with 'tag', according
2017  // to compatibility option 'opt'.
2018  // For opt = 0 tags starting with 'tag'
2019  // for opt = 1 tags containing the wild card '*' are matched.
2020  // Return number of entries removed
2021  EPNAME("PFile::RemoveEntries");
2022 
2023  //
2024  // Get number of entries related
2025  int nm = SearchEntries(tag,opt);
2026  if (nm) {
2027  DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
2028  //
2029  // Book vector for offsets
2030  int *ofs = new int[nm];
2031  //
2032  // Get number of entries related
2033  SearchEntries(tag,0,ofs,nm);
2034  //
2035  // Read entries now
2036  int i = 0;
2037  for (; i < nm ; i++) {
2038  if (RemoveEntry(ofs[i]) == 0) {
2039  DEBUG("entry for tag '"<<tag<<"' removed from file");
2040  } else {
2041  DEBUG("entry for tag '"<<tag<<"' not found in file");
2042  }
2043  }
2044  } else {
2045  DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
2046  }
2047  // We are done
2048  return nm;
2049 }
2050 
2051 //________________________________________________________________
2052 kXR_int32 XrdSutPFile::SearchEntries(const char *tag, char opt,
2053  kXR_int32 *ofs, kXR_int32 nofs)
2054 {
2055  // Get offsets of the first nofs entries whose tag is compatible
2056  // with 'tag', according to compatibility option 'opt'.
2057  // For opt = 0 tags starting with 'tag' are searched for;
2058  // For opt = 1 tags containing the wild card '*' matching tag
2059  // are searched for.
2060  // For opt = 2 tags matching tag are searched for; tag may contain
2061  // the wild card '*'.
2062  // The caller is responsible for memory pointed by 'ofs'.
2063  // Return number of entries found (<= nofs).
2064  // If ofs = 0, return total number of entries matching the
2065  // condition.
2066 
2067  // Make sure that we got a tag
2068  if (!tag)
2069  return Err(kPFErrBadInputs,"SearchEntries");
2070 
2071  // Make sure we got an open stream
2072  bool wasopen = 0;
2073  if (Open(1,&wasopen) < 0)
2074  return -1;
2075 
2076  // Read the header
2077  XrdSutPFHeader header;
2078  if (ReadHeader(header) < 0) {
2079  if (!wasopen) Close();
2080  return -1;
2081  }
2082 
2083  // Get offset of the first index entry
2084  kXR_int32 indofs = header.indofs;
2085 
2086  // Scan entries
2087  kXR_int32 no = 0;
2088  XrdOucString smatch;
2089  if (opt == 1)
2090  smatch.assign(tag, 0);
2091  while (indofs) {
2092 
2093  // Read it out
2094  XrdSutPFEntInd ind;
2095  if (ReadInd(indofs, ind) < 0) {
2096  if (!wasopen) Close();
2097  return -1;
2098  }
2099 
2100  // Check compatibility
2101  int match = 0;
2102  if (opt == 0) {
2103  if (!strncmp(ind.name,tag,strlen(tag)))
2104  match = 1;
2105  } else if (opt == 1) {
2106  match = smatch.matches(ind.name);
2107  } else if (opt == 2) {
2108  smatch.assign(ind.name, 0);
2109  match = smatch.matches(tag);
2110  }
2111 
2112  if (match > 0 && ind.entofs > 0) {
2113  no++;
2114  if (ofs) {
2115  ofs[no-1] = indofs;
2116  if (no == nofs) {
2117  // We are done
2118  break;
2119  }
2120  }
2121  }
2122 
2123  // Next index entry
2124  indofs = ind.nxtofs;
2125  }
2126 
2127  // Close the file
2128  if (!wasopen) Close();
2129 
2130  return no;
2131 }
2132 
2133 //________________________________________________________________
2135  kXR_int32 nofs)
2136 {
2137  // Get offsets of the first nofs entries with status
2138  // kPFE_special.
2139  // The caller is responsible for memory pointed by 'ofs'.
2140  // Return number of entries found (<= nofs).
2141  // If ofs = 0, return total number of special entries.
2142 
2143  // Make sure we got an open stream
2144  bool wasopen = 0;
2145  if (Open(1,&wasopen) < 0)
2146  return -1;
2147 
2148  // Read the header
2149  XrdSutPFHeader header;
2150  if (ReadHeader(header) < 0) {
2151  if (!wasopen) Close();
2152  return -1;
2153  }
2154 
2155  // Get offset of the first index entry
2156  kXR_int32 indofs = header.indofs;
2157 
2158  // Scan entries
2159  kXR_int32 no = 0;
2160  while (indofs) {
2161 
2162  // Read index
2163  XrdSutPFEntInd ind;
2164  if (ReadInd(indofs, ind) < 0) {
2165  if (!wasopen) Close();
2166  return -1;
2167  }
2168 
2169  // If active ...
2170  if (ind.entofs > 0) {
2171 
2172  // Read entry out
2173  XrdSutPFEntry ent;
2174  if (ReadEnt(ind.entofs, ent) < 0) {
2175  if (!wasopen) Close();
2176  return -1;
2177  }
2178  // If special ...
2179  if (ent.status == kPFE_special) {
2180  // Record the offset ...
2181  no++;
2182  if (ofs) {
2183  ofs[no-1] = indofs;
2184  if (no == nofs) {
2185  // We are done
2186  break;
2187  }
2188  }
2189  }
2190  }
2191 
2192  // Next index entry
2193  indofs = ind.nxtofs;
2194  }
2195 
2196  // Close the file
2197  if (!wasopen) Close();
2198 
2199  return no;
2200 }
2201 
2202 //________________________________________________________________
2203 kXR_int32 XrdSutPFile::Err(kXR_int32 code, const char *loc,
2204  const char *em1, const char *em2)
2205 {
2206  // Save code and, if requested, format and print an error
2207  // message
2208  EPNAME("PFile::Err");
2209 
2210  char buf[XrdSutMAXBUF];
2211  int fd = 0, lp = 0, lt = 0;
2212 
2213  // Save code for later use
2214  fError = code;
2215 
2216  // Build string following the error code
2217  const char *errbuf = XrdSysE2T(errno);
2218  switch (code) {
2219  case kPFErrBadInputs:
2220  snprintf(buf,XrdSutMAXBUF,
2221  "XrdSutPFile::%s: bad input arguments",loc);
2222  break;
2223  case kPFErrFileAlreadyOpen:
2224  snprintf(buf,XrdSutMAXBUF,
2225  "XrdSutPFile::%s: file already open"
2226  " in incompatible mode",loc);
2227  break;
2228  case kPFErrNoFile:
2229  snprintf(buf,XrdSutMAXBUF,
2230  "XrdSutPFile::%s: file %s does not exists",
2231  loc,em1);
2232  break;
2233  case kPFErrFileRename:
2234  snprintf(buf,XrdSutMAXBUF,
2235  "XrdSutPFile::%s: error renaming file %s to %s"
2236  " (%s)",loc,em1,em2,errbuf);
2237  break;
2238  case kPFErrStat:
2239  snprintf(buf,XrdSutMAXBUF,
2240  "XrdSutPFile::%s: cannot file %s (%s)",
2241  loc,em1,errbuf);
2242  break;
2243  case kPFErrFileOpen:
2244  snprintf(buf,XrdSutMAXBUF,
2245  "XrdSutPFile::%s: cannot open file %s (%s)",
2246  loc,em1,errbuf);
2247  break;
2248  case kPFErrFileNotOpen:
2249  snprintf(buf,XrdSutMAXBUF,
2250  "XrdSutPFile::%s: file is not open", loc);
2251  break;
2252  case kPFErrLocking:
2253  fd = *((int *)em1);
2254  snprintf(buf,XrdSutMAXBUF,
2255  "XrdSutPFile::%s: cannot lock file descriptor %d (%s)",
2256  loc,fd,errbuf);
2257  break;
2258  case kPFErrUnlocking:
2259  fd = *((int *)em1);
2260  snprintf(buf,XrdSutMAXBUF,
2261  "XrdSutPFile::%s: cannot unlock file descriptor %d (%s)",
2262  loc,fd,errbuf);
2263  break;
2264  case kPFErrFileLocked:
2265  fd = *((int *)em2);
2266  snprintf(buf,XrdSutMAXBUF,
2267  "XrdSutPFile::%s: file %s is locked by process %d",
2268  loc,em1,fd);
2269  break;
2270  case kPFErrSeek:
2271  fd = *((int *)em2);
2272  snprintf(buf,XrdSutMAXBUF,
2273  "XrdSutPFile::%s: lseek %s error on descriptor %d (%s)",
2274  loc,em1,fd,errbuf);
2275  break;
2276  case kPFErrRead:
2277  fd = *((int *)em1);
2278  snprintf(buf,XrdSutMAXBUF,
2279  "XrdSutPFile::%s: read error on descriptor %d (%s)",
2280  loc,fd,errbuf);
2281  break;
2282  case kPFErrOutOfMemory:
2283  snprintf(buf,XrdSutMAXBUF,
2284  "XrdSutPFile::%s: out of memory (%s)",
2285  loc,errbuf);
2286  break;
2287  case kPFErrLenMismatch:
2288  lp = *((int *)em1);
2289  lt = *((int *)em2);
2290  snprintf(buf,XrdSutMAXBUF,
2291  "XrdSutPFile::%s: length mismatch: %d (expected: %d)",
2292  loc,lp,lt);
2293  break;
2294  case kPFErrBadOp:
2295  snprintf(buf,XrdSutMAXBUF,
2296  "XrdSutPFile::%s: bad option: %s", loc,em1);
2297  break;
2298  default:
2299  DEBUG("unknown error code: "<<code);
2300  }
2301 
2302  // Print error string if requested
2303  DEBUG(buf);
2304 
2305  // Save error string
2306  fErrStr = buf;
2307 
2308  return -1;
2309 }
int kXR_int32
Definition: XPtypes.hh:89
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define Err(p, a, b, c)
Definition: XrdNetSocket.cc:81
off_t lseek(int fildes, off_t offset, int whence)
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fcntl(int fd, int cmd,...)
int rename(const char *oldpath, const char *newpath)
ssize_t write(int fildes, const void *buf, size_t nbyte)
ssize_t read(int fildes, void *buf, size_t nbyte)
#define close(a)
Definition: XrdPosix.hh:43
int XrdSutTimeString(int t, char *st, int opt)
Definition: XrdSutAux.cc:311
#define XrdSutMAXBUF
Definition: XrdSutAux.hh:48
@ kPFE_special
@ kPFE_inactive
#define kPFEopen
Definition: XrdSutPFile.hh:60
#define kOfsJnkSiz
Definition: XrdSutPFile.hh:57
@ kPFErrUnlocking
Definition: XrdSutPFile.hh:73
@ kPFErrFileLocked
Definition: XrdSutPFile.hh:74
@ kPFErrBadInputs
Definition: XrdSutPFile.hh:65
@ kPFErrStat
Definition: XrdSutPFile.hh:69
@ kPFErrOutOfMemory
Definition: XrdSutPFile.hh:77
@ kPFErrBadOp
Definition: XrdSutPFile.hh:79
@ kPFErrFileNotOpen
Definition: XrdSutPFile.hh:71
@ kPFErrSeek
Definition: XrdSutPFile.hh:75
@ kPFErrFileOpen
Definition: XrdSutPFile.hh:70
@ kPFErrLocking
Definition: XrdSutPFile.hh:72
@ kPFErrFileRename
Definition: XrdSutPFile.hh:68
@ kPFErrFileAlreadyOpen
Definition: XrdSutPFile.hh:66
@ kPFErrRead
Definition: XrdSutPFile.hh:76
@ kPFErrNoFile
Definition: XrdSutPFile.hh:67
@ kPFErrLenMismatch
Definition: XrdSutPFile.hh:78
#define kDefFileID
Definition: XrdSutPFile.hh:48
#define kFileIDSize
Definition: XrdSutPFile.hh:47
#define kMaxLockTries
Definition: XrdSutPFile.hh:62
#define kPFEcreate
Definition: XrdSutPFile.hh:59
#define kOfsCtime
Definition: XrdSutPFile.hh:53
#define kOfsItime
Definition: XrdSutPFile.hh:54
#define kXrdIFVersion
Definition: XrdSutPFile.hh:49
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
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
void assign(const char *s, int j, int k=-1)
int matches(const char *s, char wch=' *')
kXR_int32 len
kXR_int32 entsiz
Definition: XrdSutPFile.hh:89
void SetName(const char *n=0)
Definition: XrdSutPFile.cc:78
kXR_int32 Length() const
Definition: XrdSutPFile.hh:95
kXR_int32 entofs
Definition: XrdSutPFile.hh:88
XrdSutPFEntInd & operator=(const XrdSutPFEntInd ei)
Definition: XrdSutPFile.cc:94
XrdSutPFEntInd(const char *n=0, kXR_int32 no=0, kXR_int32 eo=0, kXR_int32 es=0)
Definition: XrdSutPFile.cc:45
kXR_int32 nxtofs
Definition: XrdSutPFile.hh:87
kXR_int32 mtime
XrdSutPFBuf buf3
XrdSutPFBuf buf1
void SetName(const char *n=0)
XrdSutPFBuf buf2
kXR_int32 Length() const
XrdSutPFBuf buf4
kXR_int32 itime
Definition: XrdSutPFile.hh:107
kXR_int32 entries
Definition: XrdSutPFile.hh:108
kXR_int32 version
Definition: XrdSutPFile.hh:105
static kXR_int32 Length()
Definition: XrdSutPFile.hh:117
kXR_int32 ctime
Definition: XrdSutPFile.hh:106
kXR_int32 jnksiz
Definition: XrdSutPFile.hh:110
kXR_int32 indofs
Definition: XrdSutPFile.hh:109
char fileID[kFileIDSize]
Definition: XrdSutPFile.hh:104
XrdSutPFHeader(const char *id=" ", kXR_int32 v=0, kXR_int32 ct=0, kXR_int32 it=0, kXR_int32 ent=0, kXR_int32 ofs=0)
Definition: XrdSutPFile.cc:112
void Print() const
Definition: XrdSutPFile.cc:147
kXR_int32 UpdateCount(const char *nm, int *cnt=0, int step=1, bool reset=0)
Definition: XrdSutPFile.cc:795
kXR_int32 SearchSpecialEntries(kXR_int32 *ofs=0, kXR_int32 nofs=1)
kXR_int32 Browse(void *out=0)
kXR_int32 Trim(const char *fbak=0)
kXR_int32 WriteEntry(XrdSutPFEntry ent)
Definition: XrdSutPFile.cc:585
virtual ~XrdSutPFile()
Definition: XrdSutPFile.cc:221
kXR_int32 RemoveEntries(const char *name, char opt)
const char * Name() const
Definition: XrdSutPFile.hh:168
kXR_int32 RetrieveHeader(XrdSutPFHeader &hd)
Definition: XrdSutPFile.cc:503
kXR_int32 SearchEntries(const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
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
XrdSutPFile(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
Definition: XrdSutPFile.cc:187
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
Definition: XrdSutPFile.cc:236
kXR_int32 UpdateHeader(XrdSutPFHeader hd)
Definition: XrdSutPFile.cc:484
kXR_int32 RemoveEntry(const char *name)
kXR_int32 Open(kXR_int32 opt, bool *wasopen=0, const char *nam=0, kXR_int32 createmode=0600)
Definition: XrdSutPFile.cc:300