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 ind.name = new char[lnam+1];
1524 if (ind.name) {
1525 if ((nr = read(fFd,ind.name,lnam)) != lnam)
1526 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
1527 ind.name[lnam] = 0; // null-terminated
1528 nrdt += nr;
1529 } else
1530 return Err(kPFErrOutOfMemory,"ReadInd");
1531 }
1532
1533 return nrdt;
1534}
1535
1536//____________________________________________________________________
1537kXR_int32 XrdSutPFile::ReadEnt(kXR_int32 ofs, XrdSutPFEntry &ent)
1538{
1539 // Read ent from current position at stream
1540
1541 //
1542 // Make sure that we got an open file description
1543 if (fFd < 0)
1544 return Err(kPFErrFileNotOpen,"ReadEnt");
1545 //
1546 // Set the offset
1547 if (lseek(fFd, ofs, SEEK_SET) == -1)
1548 return Err(kPFErrSeek,"ReadEnt",
1549 "SEEK_SET",(const char *)&fFd);
1550
1551 kXR_int32 nr = 0, nrdt = 0;
1552 //
1553 // Now read the information step by step:
1554 // the status ...
1555 if ((nr = read(fFd,&ent.status,sizeof(short))) != sizeof(short))
1556 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1557 nrdt += nr;
1558 // the count var ...
1559 if ((nr = read(fFd,&ent.cnt,sizeof(short))) != sizeof(short))
1560 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1561 nrdt += nr;
1562 // the the time of modification / creation ...
1563 if ((nr = read(fFd,&ent.mtime,sizeof(kXR_int32))) != sizeof(kXR_int32))
1564 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1565 nrdt += nr;
1566 // the length of the first buffer ...
1567 if ((nr = read(fFd,&ent.buf1.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1568 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1569 nrdt += nr;
1570 // the length of the second buffer ...
1571 if ((nr = read(fFd,&ent.buf2.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1572 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1573 nrdt += nr;
1574 // the length of the third buffer ...
1575 if ((nr = read(fFd,&ent.buf3.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1576 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1577 nrdt += nr;
1578 // the length of the fourth buffer ...
1579 if ((nr = read(fFd,&ent.buf4.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
1580 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1581 nrdt += nr;
1582 // Allocate space for the first buffer and read it (if any) ...
1583 if (ent.buf1.len) {
1584 ent.buf1.buf = new char[ent.buf1.len];
1585 if (!ent.buf1.buf)
1586 return Err(kPFErrOutOfMemory,"ReadEnt");
1587 if ((nr = read(fFd,ent.buf1.buf,ent.buf1.len)) != ent.buf1.len)
1588 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1589 nrdt += nr;
1590 }
1591 // Allocate space for the second buffer and read it (if any) ...
1592 if (ent.buf2.len) {
1593 ent.buf2.buf = new char[ent.buf2.len];
1594 if (!ent.buf2.buf)
1595 return Err(kPFErrOutOfMemory,"ReadEnt");
1596 if ((nr = read(fFd,ent.buf2.buf,ent.buf2.len)) != ent.buf2.len)
1597 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1598 nrdt += nr;
1599 }
1600 // Allocate space for the third buffer and read it (if any) ...
1601 if (ent.buf3.len) {
1602 ent.buf3.buf = new char[ent.buf3.len];
1603 if (!ent.buf3.buf)
1604 return Err(kPFErrOutOfMemory,"ReadEnt");
1605 if ((nr = read(fFd,ent.buf3.buf,ent.buf3.len)) != ent.buf3.len)
1606 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1607 nrdt += nr;
1608 }
1609 // Allocate space for the fourth buffer and read it (if any) ...
1610 if (ent.buf4.len) {
1611 ent.buf4.buf = new char[ent.buf4.len];
1612 if (!ent.buf4.buf)
1613 return Err(kPFErrOutOfMemory,"ReadEnt");
1614 if ((nr = read(fFd,ent.buf4.buf,ent.buf4.len)) != ent.buf4.len)
1615 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
1616 nrdt += nr;
1617 }
1618
1619 return nrdt;
1620}
1621
1622//________________________________________________________________
1624{
1625 // Display the content of the file
1626
1627 // Make sure we got an open stream
1628 if (Open(1) < 0)
1629 return -1;
1630
1631 // Read header
1632 XrdSutPFHeader hdr;
1633 if (ReadHeader(hdr) < 0) {
1634 Close();
1635 return -1;
1636 }
1637
1638 // Time strings
1639 struct tm tst;
1640 char sctime[256] = {0};
1641 time_t ttmp = hdr.ctime;
1642 localtime_r(&ttmp,&tst);
1643 asctime_r(&tst,sctime);
1644 sctime[strlen(sctime)-1] = 0;
1645 char sitime[256] = {0};
1646 ttmp = hdr.itime;
1647 localtime_r(&ttmp,&tst);
1648 asctime_r(&tst,sitime);
1649 sitime[strlen(sitime)-1] = 0;
1650
1651 // Default is stdout
1652 FILE *out = oout ? (FILE *)oout : stdout;
1653
1654 fprintf(out,"//-----------------------------------------------------"
1655 "--------------------//\n");
1656 fprintf(out,"//\n");
1657 fprintf(out,"// File: %s\n",name);
1658 fprintf(out,"// ID: %s\n",hdr.fileID);
1659 fprintf(out,"// Version: %d\n",hdr.version);
1660 fprintf(out,"// Last change : %s (%d sec)\n",sctime,hdr.ctime);
1661 fprintf(out,"// Index change: %s (%d sec)\n",sitime,hdr.itime);
1662 fprintf(out,"//\n");
1663 fprintf(out,"// Number of Entries: %d\n",hdr.entries);
1664 fprintf(out,"// Bytes unreachable: %d\n",hdr.jnksiz);
1665 fprintf(out,"//\n");
1666
1667 if (hdr.entries > 0) {
1668
1669 // Special entries first, if any
1671 if (ns > 0) {
1672 // Allocate space for offsets
1673 kXR_int32 *sofs = new kXR_int32[ns];
1674 if (sofs) {
1675 // Get offsets
1676 ns = SearchSpecialEntries(sofs,ns);
1677 fprintf(out,"// Special entries (%d):\n",ns);
1678 int i = 0;
1679 for (; i<ns; i++) {
1680
1681 // Read entry index at ofs
1682 XrdSutPFEntInd ind;
1683 if (ReadInd(sofs[i], ind) < 0) {
1684 Close();
1685 return -1;
1686 }
1687
1688 if (ind.entofs) {
1689 // Read entry
1690 XrdSutPFEntry ent;
1691 if (ReadEnt(ind.entofs, ent) < 0) {
1692 Close();
1693 return -1;
1694 }
1695 char smt[20] = {0};
1696 XrdSutTimeString(ent.mtime,smt);
1697 std::string buffer;
1698 char buf[2048] = {0};
1699 memset(buf,0,2048);
1700 sprintf(buf,"// #%d mod:%s",i+1,smt);
1701 buffer = buf;
1702 sprintf(buf," name:%s",ind.name);
1703 buffer += buf;
1704 fprintf(out,"%s\n",buffer.c_str());
1705
1706 buffer.clear();
1707 sprintf(buf,"// buf");
1708 buffer = buf;
1709
1710 if (ent.cnt == 1) {
1711 if (ent.buf1.len && ent.buf1.buf)
1712 {
1713 sprintf(buf,": %.*s",ent.buf1.len,ent.buf1.buf);
1714 buffer += buf;
1715 }
1716 if (ent.buf2.len && ent.buf2.buf)
1717 {
1718 sprintf(buf,": %.*s",ent.buf2.len,ent.buf2.buf);
1719 buffer += buf;
1720 }
1721 if (ent.buf3.len && ent.buf3.buf)
1722 {
1723 sprintf(buf,": %.*s",ent.buf3.len,ent.buf3.buf);
1724 buffer += buf;
1725 }
1726 if (ent.buf4.len && ent.buf4.buf)
1727 {
1728 sprintf(buf,": %.*s",ent.buf4.len,ent.buf4.buf);
1729 buffer += buf;
1730 }
1731 } else {
1732 sprintf(buf,":%d:%d:%d:%d",
1733 ent.buf1.len,ent.buf2.len,ent.buf3.len,
1734 ent.buf4.len);
1735 buffer += buf;
1736 buffer += " (protected)";
1737 }
1738 fprintf(out,"%s\n",buf);
1739 }
1740 }
1741 fprintf(out,"//\n");
1742 delete[] sofs;
1743 }
1744 }
1745
1746 if (hdr.entries > ns)
1747 fprintf(out,"// Normal entries (%d):\n",hdr.entries-ns);
1748
1749 kXR_int32 nn = 0;
1750 kXR_int32 nxtofs = hdr.indofs;
1751 while (nxtofs) {
1752
1753 // Read entry index at ofs
1754 XrdSutPFEntInd ind;
1755 if (ReadInd(nxtofs, ind) < 0) {
1756 Close();
1757 return -3;
1758 }
1759
1760 if (ind.entofs) {
1761 // Read entry
1762 XrdSutPFEntry ent;
1763 if (ReadEnt(ind.entofs, ent) < 0) {
1764 Close();
1765 return -4;
1766 }
1767 if (ent.status != kPFE_special) {
1768 char smt[20] = {0};
1769 XrdSutTimeString(ent.mtime,smt);
1770
1771 nn++;
1772 fprintf(out,
1773 "// #:%d st:%d cn:%d buf:%d,%d,%d,%d mod:%s name:%s\n",
1774 nn,ent.status,ent.cnt,ent.buf1.len,ent.buf2.len,ent.buf3.len,
1775 ent.buf4.len,smt,ind.name);
1776 }
1777 }
1778
1779 // Read next
1780 nxtofs = ind.nxtofs;
1781 }
1782 fprintf(out,"//\n");
1783 }
1784 fprintf(out,"//-----------------------------------------------------"
1785 "--------------------//\n");
1786
1787 // Close the file
1788 Close();
1789
1790 return 0;
1791}
1792
1793//________________________________________________________________
1795{
1796 // Trim away unreachable entries from the file
1797 // Previous content is save in a file name fbak, the default
1798 // being 'name'.bak
1799 EPNAME("PFile::Trim");
1800
1801 // Retrieve header, first, to check if there is anything to trim
1802 XrdSutPFHeader header;
1803 if (RetrieveHeader(header) < 0)
1804 return -1;
1805 if (header.jnksiz <= 0) {
1806 DEBUG("nothing to trim - return ");
1807 return -1;
1808 }
1809
1810 // Get name of backup file
1811 char *nbak = (char *)fbak;
1812 if (!nbak) {
1813 // Use default
1814 nbak = new char[strlen(name)+5];
1815 if (!nbak)
1816 return Err(kPFErrOutOfMemory,"Trim");
1817 sprintf(nbak,"%s.bak",name);
1818 DEBUG("backup file: "<<nbak);
1819 }
1820
1821 // Move file
1822 if (rename(name,nbak) == -1)
1823 return Err(kPFErrFileRename,"Trim",name,nbak);
1824
1825 // Create new file
1826 int fdnew = Open(1);
1827 if (fdnew < 0)
1828 return -1;
1829
1830 // Open backup file
1831 int fdbck = Open(1,0,nbak);
1832 if (fdbck < 0) {
1833 Close();
1834 return -1;
1835 }
1836
1837 // Read the header from backup file
1838 fFd = fdbck;
1839 if (ReadHeader(header) < 0) {
1840 Close(fdnew); Close(fdbck);
1841 return -1;
1842 }
1843
1844 // Copy it to new file
1845 fFd = fdnew;
1846 if (WriteHeader(header) < 0) {
1847 Close(fdnew); Close(fdbck);
1848 return -1;
1849 }
1850 kXR_int32 wrofs = lseek(fdnew, 0, SEEK_CUR);
1851 if (wrofs == -1) {
1852 Close(fdnew); Close(fdbck);
1853 return Err(kPFErrSeek,"Trim",
1854 "SEEK_CUR",(const char *)&fdnew);
1855 }
1856
1857 // Read active entries now and save them to new file
1858 bool firstind = 1;
1859 XrdSutPFEntInd ind, indlast;
1860 XrdSutPFEntry ent;
1861
1862 kXR_int32 nxtofs = header.indofs;
1863 kXR_int32 lastofs = nxtofs;
1864
1865 while (nxtofs) {
1866
1867 // Read index entry
1868 fFd = fdbck;
1869 if (ReadInd(nxtofs,ind) < 0) {
1870 Close(fdnew); Close(fdbck);
1871 return -1;
1872 }
1873
1874 // Get Next index entry before updating index entry
1875 nxtofs = ind.nxtofs;
1876
1877 // Read entry, if active
1878 if (ind.entofs > 0) {
1879 fFd = fdbck;
1880 if (ReadEnt(ind.entofs,ent) < 0) {
1881 Close(fdnew); Close(fdbck);
1882 return -1;
1883 }
1884 // Update index entry
1885 ind.entofs = wrofs;
1886
1887 // Write active entry
1888 fFd = fdnew;
1889 if (WriteEnt(wrofs,ent) < 0) {
1890 Close(fdnew); Close(fdbck);
1891 return -1;
1892 }
1893
1894 // Update write offset
1895 if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1896 Close(fdnew); Close(fdbck);
1897 return Err(kPFErrSeek,"Trim",
1898 "SEEK_CUR",(const char *)&fdnew);
1899 }
1900
1901 if (firstind) {
1902 // Update header
1903 header.indofs = wrofs;
1904 firstind = 0;
1905 } else {
1906 // Update previous index entry
1907 indlast.nxtofs = wrofs;
1908 fFd = fdnew;
1909 if (WriteInd(lastofs,indlast) < 0) {
1910 Close(fdnew); Close(fdbck);
1911 return -1;
1912 }
1913 }
1914
1915 // Save this index for later updates
1916 indlast = ind;
1917 lastofs = wrofs;
1918
1919 // Last index entry, for now
1920 ind.nxtofs = 0;
1921
1922 // Write active index entry
1923 fFd = fdnew;
1924 if (WriteInd(wrofs,ind) < 0) {
1925 Close(fdnew); Close(fdbck);
1926 return -1;
1927 }
1928
1929 // Update write offset
1930 if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
1931 Close(fdnew); Close(fdbck);
1932 return Err(kPFErrSeek,"Trim",
1933 "SEEK_CUR",(const char *)&fdnew);
1934 }
1935 }
1936 }
1937
1938 // Close backup file
1939 Close(fdbck);
1940 fFd = fdnew;
1941
1942 // Update header
1943 header.ctime = (kXR_int32)time(0);
1944 header.itime = header.ctime;
1945 header.jnksiz = 0;
1946
1947 // Copy it to new file
1948 if (WriteHeader(header) < 0) {
1949 Close();;
1950 return -1;
1951 }
1952
1953 // Close the file
1954 Close();
1955
1956 return 0;
1957}
1958
1959//________________________________________________________________
1960kXR_int32 XrdSutPFile::UpdateHashTable(bool force)
1961{
1962 // Update hash table reflecting the index of the file
1963 // If force is .true. the table is recreated even if no recent
1964 // change in the index has occurred.
1965 // Returns the number of entries in the table.
1966
1967 // The file must be open
1968 if (fFd < 0)
1969 return Err(kPFErrFileNotOpen,"UpdateHashTable");
1970
1971 // Read the header
1972 XrdSutPFHeader header;
1973 if (ReadHeader(header) < 0)
1974 return -1;
1975
1976 // If no recent changes and no force option, return
1977 if (!force && header.itime < fHTutime)
1978 return 0;
1979
1980 // Clean up the table or create it
1981 if (fHashTable)
1982 fHashTable->Purge();
1983 else
1984 fHashTable = new XrdOucHash<kXR_int32>;
1985 // Make sure we have it
1986 if (!fHashTable)
1987 return Err(kPFErrOutOfMemory,"UpdateHashTable");
1988
1989 // Read entries
1990 kXR_int32 ne = 0;
1991 if (header.entries > 0) {
1992 XrdSutPFEntInd ind;
1993 kXR_int32 nxtofs = header.indofs;
1994 while (nxtofs > 0) {
1995 if (ReadInd(nxtofs, ind) < 0)
1996 return -1;
1997 ne++;
1998 // Fill the table
1999 kXR_int32 *key = new kXR_int32(nxtofs);
2000 fHashTable->Add(ind.name,key);
2001 // Go to next
2002 nxtofs = ind.nxtofs;
2003 }
2004 }
2005
2006 // Update the time stamp
2007 fHTutime = (kXR_int32)time(0);
2008
2009 return ne;
2010}
2011
2012//________________________________________________________________
2013kXR_int32 XrdSutPFile::RemoveEntries(const char *tag, char opt)
2014{
2015 // Remove entries whose tag is compatible with 'tag', according
2016 // to compatibility option 'opt'.
2017 // For opt = 0 tags starting with 'tag'
2018 // for opt = 1 tags containing the wild card '*' are matched.
2019 // Return number of entries removed
2020 EPNAME("PFile::RemoveEntries");
2021
2022 //
2023 // Get number of entries related
2024 int nm = SearchEntries(tag,opt);
2025 if (nm) {
2026 DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
2027 //
2028 // Book vector for offsets
2029 int *ofs = new int[nm];
2030 //
2031 // Get number of entries related
2032 SearchEntries(tag,0,ofs,nm);
2033 //
2034 // Read entries now
2035 int i = 0;
2036 for (; i < nm ; i++) {
2037 if (RemoveEntry(ofs[i]) == 0) {
2038 DEBUG("entry for tag '"<<tag<<"' removed from file");
2039 } else {
2040 DEBUG("entry for tag '"<<tag<<"' not found in file");
2041 }
2042 }
2043 } else {
2044 DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
2045 }
2046 // We are done
2047 return nm;
2048}
2049
2050//________________________________________________________________
2051kXR_int32 XrdSutPFile::SearchEntries(const char *tag, char opt,
2052 kXR_int32 *ofs, kXR_int32 nofs)
2053{
2054 // Get offsets of the first nofs entries whose tag is compatible
2055 // with 'tag', according to compatibility option 'opt'.
2056 // For opt = 0 tags starting with 'tag' are searched for;
2057 // For opt = 1 tags containing the wild card '*' matching tag
2058 // are searched for.
2059 // For opt = 2 tags matching tag are searched for; tag may contain
2060 // the wild card '*'.
2061 // The caller is responsible for memory pointed by 'ofs'.
2062 // Return number of entries found (<= nofs).
2063 // If ofs = 0, return total number of entries matching the
2064 // condition.
2065
2066 // Make sure that we got a tag
2067 if (!tag)
2068 return Err(kPFErrBadInputs,"SearchEntries");
2069
2070 // Make sure we got an open stream
2071 bool wasopen = 0;
2072 if (Open(1,&wasopen) < 0)
2073 return -1;
2074
2075 // Read the header
2076 XrdSutPFHeader header;
2077 if (ReadHeader(header) < 0) {
2078 if (!wasopen) Close();
2079 return -1;
2080 }
2081
2082 // Get offset of the first index entry
2083 kXR_int32 indofs = header.indofs;
2084
2085 // Scan entries
2086 kXR_int32 no = 0;
2087 XrdOucString smatch;
2088 if (opt == 1)
2089 smatch.assign(tag, 0);
2090 while (indofs) {
2091
2092 // Read it out
2093 XrdSutPFEntInd ind;
2094 if (ReadInd(indofs, ind) < 0) {
2095 if (!wasopen) Close();
2096 return -1;
2097 }
2098
2099 // Check compatibility
2100 int match = 0;
2101 if (opt == 0) {
2102 if (!strncmp(ind.name,tag,strlen(tag)))
2103 match = 1;
2104 } else if (opt == 1) {
2105 match = smatch.matches(ind.name);
2106 } else if (opt == 2) {
2107 smatch.assign(ind.name, 0);
2108 match = smatch.matches(tag);
2109 }
2110
2111 if (match > 0 && ind.entofs > 0) {
2112 no++;
2113 if (ofs) {
2114 ofs[no-1] = indofs;
2115 if (no == nofs) {
2116 // We are done
2117 break;
2118 }
2119 }
2120 }
2121
2122 // Next index entry
2123 indofs = ind.nxtofs;
2124 }
2125
2126 // Close the file
2127 if (!wasopen) Close();
2128
2129 return no;
2130}
2131
2132//________________________________________________________________
2134 kXR_int32 nofs)
2135{
2136 // Get offsets of the first nofs entries with status
2137 // kPFE_special.
2138 // The caller is responsible for memory pointed by 'ofs'.
2139 // Return number of entries found (<= nofs).
2140 // If ofs = 0, return total number of special entries.
2141
2142 // Make sure we got an open stream
2143 bool wasopen = 0;
2144 if (Open(1,&wasopen) < 0)
2145 return -1;
2146
2147 // Read the header
2148 XrdSutPFHeader header;
2149 if (ReadHeader(header) < 0) {
2150 if (!wasopen) Close();
2151 return -1;
2152 }
2153
2154 // Get offset of the first index entry
2155 kXR_int32 indofs = header.indofs;
2156
2157 // Scan entries
2158 kXR_int32 no = 0;
2159 while (indofs) {
2160
2161 // Read index
2162 XrdSutPFEntInd ind;
2163 if (ReadInd(indofs, ind) < 0) {
2164 if (!wasopen) Close();
2165 return -1;
2166 }
2167
2168 // If active ...
2169 if (ind.entofs > 0) {
2170
2171 // Read entry out
2172 XrdSutPFEntry ent;
2173 if (ReadEnt(ind.entofs, ent) < 0) {
2174 if (!wasopen) Close();
2175 return -1;
2176 }
2177 // If special ...
2178 if (ent.status == kPFE_special) {
2179 // Record the offset ...
2180 no++;
2181 if (ofs) {
2182 ofs[no-1] = indofs;
2183 if (no == nofs) {
2184 // We are done
2185 break;
2186 }
2187 }
2188 }
2189 }
2190
2191 // Next index entry
2192 indofs = ind.nxtofs;
2193 }
2194
2195 // Close the file
2196 if (!wasopen) Close();
2197
2198 return no;
2199}
2200
2201//________________________________________________________________
2202kXR_int32 XrdSutPFile::Err(kXR_int32 code, const char *loc,
2203 const char *em1, const char *em2)
2204{
2205 // Save code and, if requested, format and print an error
2206 // message
2207 EPNAME("PFile::Err");
2208
2209 char buf[XrdSutMAXBUF];
2210 int fd = 0, lp = 0, lt = 0;
2211
2212 // Save code for later use
2213 fError = code;
2214
2215 // Build string following the error code
2216 const char *errbuf = XrdSysE2T(errno);
2217 switch (code) {
2218 case kPFErrBadInputs:
2219 snprintf(buf,XrdSutMAXBUF,
2220 "XrdSutPFile::%s: bad input arguments",loc);
2221 break;
2223 snprintf(buf,XrdSutMAXBUF,
2224 "XrdSutPFile::%s: file already open"
2225 " in incompatible mode",loc);
2226 break;
2227 case kPFErrNoFile:
2228 snprintf(buf,XrdSutMAXBUF,
2229 "XrdSutPFile::%s: file %s does not exists",
2230 loc,em1);
2231 break;
2232 case kPFErrFileRename:
2233 snprintf(buf,XrdSutMAXBUF,
2234 "XrdSutPFile::%s: error renaming file %s to %s"
2235 " (%s)",loc,em1,em2,errbuf);
2236 break;
2237 case kPFErrStat:
2238 snprintf(buf,XrdSutMAXBUF,
2239 "XrdSutPFile::%s: cannot file %s (%s)",
2240 loc,em1,errbuf);
2241 break;
2242 case kPFErrFileOpen:
2243 snprintf(buf,XrdSutMAXBUF,
2244 "XrdSutPFile::%s: cannot open file %s (%s)",
2245 loc,em1,errbuf);
2246 break;
2247 case kPFErrFileNotOpen:
2248 snprintf(buf,XrdSutMAXBUF,
2249 "XrdSutPFile::%s: file is not open", loc);
2250 break;
2251 case kPFErrLocking:
2252 fd = *((int *)em1);
2253 snprintf(buf,XrdSutMAXBUF,
2254 "XrdSutPFile::%s: cannot lock file descriptor %d (%s)",
2255 loc,fd,errbuf);
2256 break;
2257 case kPFErrUnlocking:
2258 fd = *((int *)em1);
2259 snprintf(buf,XrdSutMAXBUF,
2260 "XrdSutPFile::%s: cannot unlock file descriptor %d (%s)",
2261 loc,fd,errbuf);
2262 break;
2263 case kPFErrFileLocked:
2264 fd = *((int *)em2);
2265 snprintf(buf,XrdSutMAXBUF,
2266 "XrdSutPFile::%s: file %s is locked by process %d",
2267 loc,em1,fd);
2268 break;
2269 case kPFErrSeek:
2270 fd = *((int *)em2);
2271 snprintf(buf,XrdSutMAXBUF,
2272 "XrdSutPFile::%s: lseek %s error on descriptor %d (%s)",
2273 loc,em1,fd,errbuf);
2274 break;
2275 case kPFErrRead:
2276 fd = *((int *)em1);
2277 snprintf(buf,XrdSutMAXBUF,
2278 "XrdSutPFile::%s: read error on descriptor %d (%s)",
2279 loc,fd,errbuf);
2280 break;
2281 case kPFErrOutOfMemory:
2282 snprintf(buf,XrdSutMAXBUF,
2283 "XrdSutPFile::%s: out of memory (%s)",
2284 loc,errbuf);
2285 break;
2286 case kPFErrLenMismatch:
2287 lp = *((int *)em1);
2288 lt = *((int *)em2);
2289 snprintf(buf,XrdSutMAXBUF,
2290 "XrdSutPFile::%s: length mismatch: %d (expected: %d)",
2291 loc,lp,lt);
2292 break;
2293 case kPFErrBadOp:
2294 snprintf(buf,XrdSutMAXBUF,
2295 "XrdSutPFile::%s: bad option: %s", loc,em1);
2296 break;
2297 default:
2298 DEBUG("unknown error code: "<<code);
2299 }
2300
2301 // Print error string if requested
2302 DEBUG(buf);
2303
2304 // Save error string
2305 fErrStr = buf;
2306
2307 return -1;
2308}
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:43
#define lseek(a, b, c)
Definition XrdPosix.hh:47
#define write(a, b, c)
Definition XrdPosix.hh:110
#define open
Definition XrdPosix.hh:71
#define stat(a, b)
Definition XrdPosix.hh:96
#define rename(a, b)
Definition XrdPosix.hh:87
#define read(a, b, c)
Definition XrdPosix.hh:77
int XrdSutTimeString(int t, char *st, int opt)
Definition XrdSutAux.cc:311
#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:99
T * Add(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default)
T * Find(const char *KeyVal, time_t *KeyTime=0)
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)