XRootD
Loading...
Searching...
No Matches
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"
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//_________________________________________________________________
78void 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//________________________________________________________________
187XrdSutPFile::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//________________________________________________________________
236bool 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);
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//_________________________________________________________________
523kXR_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//________________________________________________________________
795kXR_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//_________________________________________________________________
1269kXR_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//__________________________________________________________________
1293kXR_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//__________________________________________________________________
1350kXR_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//__________________________________________________________________
1432kXR_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//_____________________________________________________________________
1483kXR_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//____________________________________________________________________
1538kXR_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//________________________________________________________________
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//________________________________________________________________
1961kXR_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//________________________________________________________________
2014kXR_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//________________________________________________________________
2052kXR_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//________________________________________________________________
2203kXR_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;
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)
#define EPNAME(x)
#define Err(p, a, b, c)
int fcntl(int fd, int cmd,...)
#define close(a)
Definition XrdPosix.hh:48
#define lseek(a, b, c)
Definition XrdPosix.hh:52
#define write(a, b, c)
Definition XrdPosix.hh:115
#define open
Definition XrdPosix.hh:76
#define stat(a, b)
Definition XrdPosix.hh:101
#define rename(a, b)
Definition XrdPosix.hh:92
#define read(a, b, c)
Definition XrdPosix.hh:82
int XrdSutTimeString(int t, char *st, int opt)
Definition XrdSutAux.cc:305
#define XrdSutMAXBUF
Definition XrdSutAux.hh:48
@ kPFE_special
@ kPFE_inactive
#define kPFEopen
#define kOfsJnkSiz
@ kPFErrUnlocking
@ kPFErrFileLocked
@ kPFErrBadInputs
@ kPFErrStat
@ kPFErrOutOfMemory
@ kPFErrBadOp
@ kPFErrFileNotOpen
@ kPFErrSeek
@ kPFErrFileOpen
@ kPFErrLocking
@ kPFErrFileRename
@ kPFErrFileAlreadyOpen
@ kPFErrRead
@ kPFErrNoFile
@ kPFErrLenMismatch
#define kDefFileID
#define kFileIDSize
#define kMaxLockTries
#define kPFEcreate
#define kOfsCtime
#define kOfsItime
#define kXrdIFVersion
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
T * Add(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default)
void assign(const char *s, int j, int k=-1)
int matches(const char *s, char wch=' *')
const char * c_str() const
kXR_int32 len
kXR_int32 entsiz
void SetName(const char *n=0)
kXR_int32 Length() const
kXR_int32 entofs
XrdSutPFEntInd & operator=(const XrdSutPFEntInd ei)
XrdSutPFEntInd(const char *n=0, kXR_int32 no=0, kXR_int32 eo=0, kXR_int32 es=0)
kXR_int32 nxtofs
kXR_int32 mtime
XrdSutPFBuf buf3
XrdSutPFBuf buf1
void SetName(const char *n=0)
XrdSutPFBuf buf2
kXR_int32 Length() const
XrdSutPFBuf buf4
kXR_int32 itime
kXR_int32 entries
kXR_int32 version
static kXR_int32 Length()
kXR_int32 ctime
kXR_int32 jnksiz
kXR_int32 indofs
char fileID[kFileIDSize]
XrdSutPFHeader(const char *id=" ", kXR_int32 v=0, kXR_int32 ct=0, kXR_int32 it=0, kXR_int32 ent=0, kXR_int32 ofs=0)
void Print() const
kXR_int32 UpdateCount(const char *nm, int *cnt=0, int step=1, bool reset=0)
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)
virtual ~XrdSutPFile()
kXR_int32 RemoveEntries(const char *name, char opt)
kXR_int32 RetrieveHeader(XrdSutPFHeader &hd)
kXR_int32 SearchEntries(const char *name, char opt, kXR_int32 *ofs=0, kXR_int32 nofs=1)
kXR_int32 Close(kXR_int32 d=-1)
kXR_int32 ReadEntry(const char *name, XrdSutPFEntry &ent, int opt=0)
XrdSutPFile(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
bool Init(const char *n, kXR_int32 openmode=kPFEcreate, kXR_int32 createmode=0600, bool hashtab=1)
kXR_int32 UpdateHeader(XrdSutPFHeader hd)
const char * Name() const
kXR_int32 RemoveEntry(const char *name)
kXR_int32 Open(kXR_int32 opt, bool *wasopen=0, const char *nam=0, kXR_int32 createmode=0600)