00001
00002
00003 const char *XrdSutPFileCVSID = "$Id: XrdSutPFile.cc 30949 2009-11-02 16:37:58Z ganis $";
00004 #include <stdio.h>
00005 #include <string.h>
00006 #include <unistd.h>
00007 #include <stdlib.h>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <fcntl.h>
00011 #include <errno.h>
00012 #include <time.h>
00013
00014 #include "XrdSut/XrdSutAux.hh"
00015 #include "XrdSut/XrdSutPFEntry.hh"
00016 #include "XrdSut/XrdSutPFile.hh"
00017 #include "XrdSut/XrdSutTrace.hh"
00018
00019
00020 XrdSutPFEntInd::XrdSutPFEntInd(const char *n, kXR_int32 no,
00021 kXR_int32 eo, kXR_int32 es)
00022 {
00023
00024
00025 name = 0;
00026 if (n) {
00027 name = new char[strlen(n)+1];
00028 if (name)
00029 strcpy(name,n);
00030 }
00031 nxtofs = no;
00032 entofs = eo;
00033 entsiz = es;
00034 }
00035
00036
00037 XrdSutPFEntInd::XrdSutPFEntInd(const XrdSutPFEntInd &ei)
00038 {
00039
00040
00041 name = 0;
00042 if (ei.name) {
00043 name = new char[strlen(ei.name)+1];
00044 if (name)
00045 strcpy(name,ei.name);
00046 }
00047 nxtofs = ei.nxtofs;
00048 entofs = ei.entofs;
00049 entsiz = ei.entsiz;
00050 }
00051
00052
00053 void XrdSutPFEntInd::SetName(const char *n)
00054 {
00055
00056
00057 if (name) {
00058 delete[] name;
00059 name = 0;
00060 }
00061 if (n) {
00062 name = new char[strlen(n)+1];
00063 if (name)
00064 strcpy(name,n);
00065 }
00066 }
00067
00068
00069 XrdSutPFEntInd& XrdSutPFEntInd::operator=(const XrdSutPFEntInd ei)
00070 {
00071
00072
00073 name = 0;
00074 if (ei.name) {
00075 name = new char[strlen(ei.name)+1];
00076 if (name)
00077 strcpy(name,ei.name);
00078 }
00079 nxtofs = ei.nxtofs;
00080 entofs = ei.entofs;
00081 entsiz = ei.entsiz;
00082
00083 return *this;
00084 }
00085
00086
00087 XrdSutPFHeader::XrdSutPFHeader(const char *id, kXR_int32 v, kXR_int32 ct,
00088 kXR_int32 it, kXR_int32 ent, kXR_int32 ofs)
00089 {
00090
00091
00092 memset(fileID,0,kFileIDSize);
00093 if (id) {
00094 kXR_int32 lid = strlen(id);
00095 if (lid > kFileIDSize)
00096 lid = kFileIDSize;
00097 memcpy(fileID,id,lid);
00098 }
00099 version = v;
00100 ctime = ct;
00101 itime = it;
00102 entries = ent;
00103 indofs = ofs;
00104 jnksiz = 0;
00105 }
00106
00107
00108 XrdSutPFHeader::XrdSutPFHeader(const XrdSutPFHeader &fh)
00109 {
00110
00111
00112 memcpy(fileID,fh.fileID,kFileIDSize);
00113 version = fh.version;
00114 ctime = fh.ctime;
00115 itime = fh.itime;
00116 entries = fh.entries;
00117 indofs = fh.indofs;
00118 jnksiz = fh.jnksiz;
00119 }
00120
00121
00122 void XrdSutPFHeader::Print() const
00123 {
00124
00125
00126 struct tm tst;
00127
00128
00129 char sctime[256] = {0};
00130 time_t ttmp = ctime;
00131 localtime_r(&ttmp,&tst);
00132 asctime_r(&tst,sctime);
00133 sctime[strlen(sctime)-1] = 0;
00134
00135
00136 char sitime[256] = {0};
00137 ttmp = itime;
00138 localtime_r(&ttmp,&tst);
00139 asctime_r(&tst,sitime);
00140 sitime[strlen(sitime)-1] = 0;
00141
00142 fprintf(stdout,
00143 "//------------------------------------"
00144 "------------------------------//\n"
00145 "// \n"
00146 "// File Header dump \n"
00147 "// \n"
00148 "// File ID: %s \n"
00149 "// version: %d \n"
00150 "// last changed on: %s (%d sec) \n"
00151 "// index changed on: %s (%d sec) \n"
00152 "// entries: %d \n"
00153 "// unreachable: %d \n"
00154 "// first ofs: %d \n"
00155 "// \n"
00156 "//------------------------------------"
00157 "------------------------------//\n",
00158 fileID,version,sctime,ctime,sitime,itime,entries,jnksiz,indofs);
00159 }
00160
00161
00162 XrdSutPFile::XrdSutPFile(const char *n, kXR_int32 openmode,
00163 kXR_int32 createmode, bool hashtab)
00164 {
00165
00166
00167 name = 0;
00168 if (n) {
00169 name = new char[strlen(n)+1];
00170 if (name)
00171 strcpy(name,n);
00172 }
00173 valid = 0;
00174 fFd = -1;
00175 fHTutime = -1;
00176 fHashTable = 0;
00177
00178 valid = Init(n, openmode, createmode, hashtab);
00179 }
00180
00181
00182 XrdSutPFile::XrdSutPFile(const XrdSutPFile &f)
00183 {
00184
00185
00186 name = 0;
00187 if (f.name) {
00188 name = new char[strlen(f.name)+1];
00189 if (name)
00190 strcpy(name,f.name);
00191 }
00192 fFd = f.fFd ;
00193 }
00194
00195
00196 XrdSutPFile::~XrdSutPFile()
00197 {
00198
00199
00200 if (name)
00201 delete[] name;
00202 name = 0;
00203 if (fHashTable)
00204 delete fHashTable;
00205 fHashTable = 0;
00206
00207 Close();
00208 }
00209
00210
00211 bool XrdSutPFile::Init(const char *n, kXR_int32 openmode,
00212 kXR_int32 createmode, bool hashtab)
00213 {
00214
00215
00216
00217 Close();
00218
00219
00220 if (name)
00221 delete[] name;
00222 name = 0;
00223 if (n) {
00224 name = new char[strlen(n)+1];
00225 if (name)
00226 strcpy(name,n);
00227 }
00228 valid = 0;
00229 fFd = -1;
00230 fHTutime = -1;
00231 if (fHashTable)
00232 delete fHashTable;
00233 fHashTable = 0;
00234
00235
00236 if (!name)
00237 return 0;
00238
00239
00240 bool create = (openmode & kPFEcreate);
00241 bool leaveopen = (openmode & kPFEopen);
00242
00243
00244 struct stat st;
00245 if (stat(name, &st) == -1) {
00246 if (errno == ENOENT) {
00247 if (create) {
00248 if (Open(1,0,0,createmode) > 0) {
00249 kXR_int32 ct = (kXR_int32)time(0);
00250 XrdSutPFHeader hdr(kDefFileID,kXrdIFVersion,ct,ct,0,0);
00251 WriteHeader(hdr);
00252 valid = 1;
00253 if (!leaveopen)
00254 Close();
00255 }
00256 } else {
00257 Err(kPFErrNoFile,"Init",name);
00258 }
00259 }
00260 } else {
00261
00262 if (Open(1) > 0) {
00263 if (hashtab)
00264 UpdateHashTable();
00265 valid = 1;
00266 if (!leaveopen)
00267 Close();
00268 }
00269 }
00270
00271 return valid;
00272 }
00273
00274
00275 kXR_int32 XrdSutPFile::Open(kXR_int32 opt, bool *wasopen,
00276 const char *nam, kXR_int32 createmode)
00277 {
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 XrdOucString copt(opt);
00293
00294
00295 if (wasopen) *wasopen = 0;
00296
00297
00298 char *fnam = (char *)nam;
00299 if (!fnam)
00300 fnam = name;
00301 if (!fnam)
00302 return Err(kPFErrBadInputs,"Open");
00303
00304
00305 if (!nam && fFd > -1) {
00306 if (opt > 0) {
00307
00308 long omode = 0;
00309 if (fcntl(fFd, F_GETFL, &omode) != -1) {
00310 if (!(omode | O_WRONLY))
00311 return Err(kPFErrFileAlreadyOpen,"Open");
00312 }
00313 }
00314 if (wasopen) *wasopen = 1;
00315 return fFd;
00316 }
00317
00318
00319 bool newfile = 0;
00320 struct stat st;
00321 if (stat(fnam, &st) == -1) {
00322 if (errno != ENOENT) {
00323 return Err(kPFErrNoFile,"Open",fnam);
00324 } else {
00325 if (opt == 0)
00326 return Err(kPFErrStat,"Open",fnam);
00327 newfile = 1;
00328 }
00329 }
00330
00331
00332 if (!nam)
00333 fFd = -1;
00334 kXR_int32 fd = -1;
00335
00336
00337
00338 char *pn = strstr(fnam,"XXXXXX");
00339 if (pn && (pn == (fnam + strlen(fnam) - 6))) {
00340 if (opt > 0 && newfile) {
00341 fd = mkstemp(fnam);
00342 if (fd <= -1)
00343 return Err(kPFErrFileOpen,"Open",fnam);
00344 }
00345 }
00346
00347
00348 if (fd <= -1) {
00349 kXR_int32 mode = 0;
00350 switch (opt) {
00351 case 2:
00352
00353
00354 mode |= O_TRUNC ;
00355 case 1:
00356
00357
00358 mode |= O_RDWR ;
00359 if (newfile)
00360 mode |= O_CREAT ;
00361 break;
00362 case 0:
00363
00364
00365 mode = O_RDONLY ;
00366 break;
00367 default:
00368
00369
00370 return Err(kPFErrBadOp,"Open",copt.c_str());
00371 }
00372
00373
00374 fd = open(fnam, mode, createmode);
00375 if (fd <= -1)
00376 return Err(kPFErrFileOpen,"Open",fnam);
00377 }
00378
00379
00380
00381 int lockmode = (opt > 0) ? (F_WRLCK | F_RDLCK) : F_RDLCK;
00382 int lck = kMaxLockTries;
00383 int rc = 0;
00384 while (lck && rc == -1) {
00385 #ifdef __macos__
00386 struct flock flck = {0, 0, 0, lockmode, SEEK_SET};
00387 #else
00388 struct flock flck = {lockmode, SEEK_SET, 0, 0};
00389 #endif
00390 if ((rc = fcntl(fd, F_SETLK, &flck)) == 0)
00391 break;
00392 struct timespec lftp, rqtp = {1, 0};
00393 while (nanosleep(&rqtp, &lftp) < 0 && errno == EINTR) {
00394 rqtp.tv_sec = lftp.tv_sec;
00395 rqtp.tv_nsec = lftp.tv_nsec;
00396 }
00397 }
00398 if (rc == -1) {
00399 if (errno == EACCES || errno == EAGAIN) {
00400
00401 int pid = -1;
00402 #ifdef __macos__
00403 struct flock flck = {0, 0, 0, lockmode, SEEK_SET};
00404 #else
00405 struct flock flck = {lockmode, SEEK_SET, 0, 0};
00406 #endif
00407 if (fcntl(fd,F_GETLK,&flck) != -1)
00408 pid = flck.l_pid;
00409 close(fd);
00410 return Err(kPFErrFileLocked,"Open",fnam,(const char *)&pid);
00411 } else {
00412
00413 return Err(kPFErrLocking,"Open",fnam,(const char *)&fd);
00414 }
00415 }
00416
00417
00418 if (!nam)
00419 fFd = fd;
00420 return fd;
00421 }
00422
00423
00424 kXR_int32 XrdSutPFile::Close(kXR_int32 fd)
00425 {
00426
00427
00428
00429
00430 if (fd < 0)
00431 fd = fFd;
00432 if (fd < 0)
00433 return 0;
00434
00435
00436
00437 #ifdef __macos__
00438 struct flock flck = {0, 0, 0, F_UNLCK, SEEK_SET};
00439 #else
00440 struct flock flck = {F_UNLCK, SEEK_SET, 0, 0};
00441 #endif
00442 if (fcntl(fd, F_SETLK, &flck) == -1) {
00443 close(fd);
00444 return Err(kPFErrUnlocking,"Close",(const char *)&fd);
00445 }
00446
00447
00448
00449 close(fd);
00450
00451
00452 if (fd == fFd)
00453 fFd = -1;
00454
00455 return 0;
00456 }
00457
00458
00459 kXR_int32 XrdSutPFile::UpdateHeader(XrdSutPFHeader hd)
00460 {
00461
00462
00463
00464
00465 if (Open(1) < 0)
00466 return -1;
00467
00468
00469 kXR_int32 nw = WriteHeader(hd);
00470
00471
00472 Close();
00473
00474 return nw;
00475 }
00476
00477
00478 kXR_int32 XrdSutPFile::RetrieveHeader(XrdSutPFHeader &hd)
00479 {
00480
00481
00482
00483
00484 bool wasopen = 0;
00485 if (Open(1, &wasopen) < 0)
00486 return -1;
00487
00488
00489 kXR_int32 rc = ReadHeader(hd);
00490
00491
00492 if (!wasopen) Close();
00493
00494 return rc;
00495 }
00496
00497
00498 kXR_int32 XrdSutPFile::WriteHeader(XrdSutPFHeader hd)
00499 {
00500
00501
00502
00503
00504
00505 kXR_int32 ltot = hd.Length();
00506
00507
00508 char *bout = new char[ltot];
00509 if (!bout)
00510 return Err(kPFErrOutOfMemory,"WriteHeader");
00511
00512
00513 kXR_int32 lp = 0;
00514
00515 memcpy(bout+lp,hd.fileID,kFileIDSize);
00516 lp += kFileIDSize;
00517
00518 memcpy(bout+lp,&hd.version,sizeof(kXR_int32));
00519 lp += sizeof(kXR_int32);
00520
00521 memcpy(bout+lp,&hd.ctime,sizeof(kXR_int32));
00522 lp += sizeof(kXR_int32);
00523
00524 memcpy(bout+lp,&hd.itime,sizeof(kXR_int32));
00525 lp += sizeof(kXR_int32);
00526
00527 memcpy(bout+lp,&hd.entries,sizeof(kXR_int32));
00528 lp += sizeof(kXR_int32);
00529
00530 memcpy(bout+lp,&hd.indofs,sizeof(kXR_int32));
00531 lp += sizeof(kXR_int32);
00532
00533 memcpy(bout+lp,&hd.jnksiz,sizeof(kXR_int32));
00534 lp += sizeof(kXR_int32);
00535
00536 if (lp != ltot) {
00537 if (bout) delete[] bout;
00538 return Err(kPFErrLenMismatch,"WriteHeader",
00539 (const char *)&lp, (const char *)<ot);
00540 }
00541
00542
00543 if (fFd < 0)
00544 return Err(kPFErrFileNotOpen,"WriteHeader");
00545
00546
00547 if (lseek(fFd, 0, SEEK_SET) == -1) {
00548 return Err(kPFErrSeek,"WriteHeader","SEEK_SET",(const char *)&fFd);
00549 }
00550
00551 kXR_int32 nw = 0;
00552
00553 while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
00554 errno = 0;
00555
00556 return nw;
00557 }
00558
00559
00560 kXR_int32 XrdSutPFile::WriteEntry(XrdSutPFEntry ent)
00561 {
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571 if (!ent.name)
00572 return Err(kPFErrBadInputs,"WriteEntry");
00573
00574
00575
00576 bool wasopen = 0;
00577 if (Open(1, &wasopen) < 0)
00578 return -1;
00579
00580 kXR_int32 ofs = 0;
00581 kXR_int32 nw = 0;
00582 kXR_int32 indofs = 0;
00583
00584 XrdSutPFHeader header;
00585 if (ReadHeader(header) < 0) {
00586 if (!wasopen) Close();
00587 return -1;
00588 }
00589 if ((ofs = lseek(fFd, 0, SEEK_CUR)) == -1) {
00590 if (!wasopen) Close();
00591 return Err(kPFErrSeek,"WriteEntry","SEEK_CUR",(const char *)&fFd);
00592 }
00593
00594 XrdSutPFEntInd ind;
00595
00596 if (header.entries == 0) {
00597 if ((nw = WriteEnt(ofs, ent)) < 0) {
00598 if (!wasopen) Close();
00599 return -1;
00600 }
00601 ind.SetName(ent.name);
00602 ind.nxtofs = 0;
00603 ind.entofs = ofs;
00604 ind.entsiz = nw;
00605 indofs = ofs + nw;
00606 if (WriteInd(indofs, ind) < 0) {
00607 if (!wasopen) Close();
00608 return -1;
00609 }
00610
00611 header.entries = 1;
00612 header.indofs = indofs;
00613 header.ctime = time(0);
00614 header.itime = header.ctime;
00615 if (WriteHeader(header) < 0) {
00616 if (!wasopen) Close();
00617 return -1;
00618 }
00619 if (!wasopen) Close();
00620 return nw;
00621 }
00622
00623
00624 kXR_int32 nr = 1;
00625 bool found = 0;
00626 indofs = header.indofs;
00627 kXR_int32 lastindofs = indofs;
00628 while (!found && nr > 0 && indofs > 0) {
00629 nr = ReadInd(indofs, ind);
00630 if (nr) {
00631 if (ind.entofs > 0 && !strcmp(ent.name,ind.name)) {
00632 found = 1;
00633 break;
00634 }
00635 lastindofs = indofs;
00636 indofs = ind.nxtofs;
00637 }
00638 }
00639
00640
00641
00642
00643
00644 if (found) {
00645
00646 kXR_int32 ct = 0;
00647 if (ind.entsiz >= ent.Length()) {
00648
00649 if ((nw = WriteEnt(ind.entofs, ent)) < 0) {
00650 if (!wasopen) Close();
00651 return -1;
00652 }
00653 } else {
00654
00655 kXR_int32 entofs = 0;
00656 if ((entofs = lseek(fFd, 0, SEEK_END)) == -1) {
00657 if (!wasopen) Close();
00658 return Err(kPFErrSeek,"WriteEntry",
00659 "SEEK_END",(const char *)&fFd);
00660 }
00661 if ((nw = WriteEnt(entofs, ent)) < 0) {
00662 if (!wasopen) Close();
00663 return -1;
00664 }
00665
00666 kXR_int32 wrtofs = ind.entofs;
00667 if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
00668 if (!wasopen) Close();
00669 return Err(kPFErrSeek,"WriteEntry",
00670 "SEEK_SET",(const char *)&fFd);
00671 }
00672 short status = kPFE_inactive;
00673 while (write(fFd, &status, sizeof(short)) < 0 &&
00674 errno == EINTR) errno = 0;
00675
00676 if (Reset(wrtofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
00677 if (!wasopen) Close();
00678 return -1;
00679 }
00680
00681 header.jnksiz += ind.entsiz;
00682 if (lseek(fFd, kOfsJnkSiz, SEEK_SET) == -1) {
00683 if (!wasopen) Close();
00684 return Err(kPFErrSeek,"WriteEntry",
00685 "SEEK_SET",(const char *)&fFd);
00686 }
00687 while (write(fFd, &header.jnksiz, sizeof(kXR_int32)) < 0 &&
00688 errno == EINTR) errno = 0;
00689
00690 wrtofs = indofs + 2*sizeof(kXR_int32);
00691 if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
00692 if (!wasopen) Close();
00693 return Err(kPFErrSeek,"WriteEntry",
00694 "SEEK_SET",(const char *)&fFd);
00695 }
00696 while (write(fFd, &entofs, sizeof(kXR_int32)) < 0 &&
00697 errno == EINTR) errno = 0;
00698 while (write(fFd, &nw, sizeof(kXR_int32)) < 0 &&
00699 errno == EINTR) errno = 0;
00700
00701 ct = (kXR_int32)time(0);
00702 header.itime = ct;
00703 if (lseek(fFd, kOfsItime, SEEK_SET) == -1) {
00704 if (!wasopen) Close();
00705 return Err(kPFErrSeek,"WriteEntry",
00706 "SEEK_SET",(const char *)&fFd);
00707 }
00708 while (write(fFd, &header.itime, sizeof(kXR_int32)) < 0 &&
00709 errno == EINTR) errno = 0;
00710 }
00711
00712 header.ctime = (ct > 0) ? ct : time(0);
00713 if (lseek(fFd, kOfsCtime, SEEK_SET) == -1) {
00714 if (!wasopen) Close();
00715 return Err(kPFErrSeek,"WriteEntry",
00716 "SEEK_SET",(const char *)&fFd);
00717 }
00718 while (write(fFd, &header.ctime, sizeof(kXR_int32)) < 0 &&
00719 errno == EINTR) errno = 0;
00720 if (!wasopen) Close();
00721 return nw;
00722 }
00723
00724
00725
00726 if ((ofs = lseek(fFd, 0, SEEK_END)) == -1) {
00727 if (!wasopen) Close();
00728 return Err(kPFErrSeek,"WriteEntry",
00729 "SEEK_END",(const char *)&fFd);
00730 }
00731 if ((nw = WriteEnt(ofs, ent)) < 0) {
00732 if (!wasopen) Close();
00733 return -1;
00734 }
00735
00736
00737 XrdSutPFEntInd newind(ent.name, 0, ofs, nw);
00738 if (WriteInd(ofs+nw, newind) < 0) {
00739 if (!wasopen) Close();
00740 return -1;
00741 }
00742
00743
00744 ind.nxtofs = ofs + nw;
00745 kXR_int32 wrtofs = lastindofs + sizeof(kXR_int32);
00746 if (lseek(fFd, wrtofs, SEEK_SET) == -1) {
00747 if (!wasopen) Close();
00748 return Err(kPFErrSeek,"WriteEntry",
00749 "SEEK_SET",(const char *)&fFd);
00750 }
00751 while (write(fFd, &ind.nxtofs, sizeof(kXR_int32)) < 0 &&
00752 errno == EINTR) errno = 0;
00753
00754
00755 header.entries += 1;
00756 header.ctime = time(0);
00757 header.itime = header.ctime;
00758 if (WriteHeader(header) < 0) {
00759 if (!wasopen) Close();
00760 return -1;
00761 }
00762
00763
00764 if (!wasopen) Close();
00765
00766 return nw;
00767 }
00768
00769
00770 kXR_int32 XrdSutPFile::UpdateCount(const char *tag, int *cnt,
00771 int step, bool reset)
00772 {
00773
00774
00775
00776
00777
00778
00779
00780
00781 if (!tag)
00782 return Err(kPFErrBadInputs,"UpdateCount");
00783
00784
00785 if (Open(1) < 0)
00786 return -1;
00787
00788
00789 XrdSutPFHeader header;
00790 if (ReadHeader(header) < 0) {
00791 Close();
00792 return -1;
00793 }
00794
00795
00796 if (fHashTable && header.itime > fHTutime) {
00797
00798 if (UpdateHashTable() < 0) {
00799 Close();
00800 return -1;
00801 }
00802 }
00803
00804
00805 XrdSutPFEntInd ind;
00806 bool found = 0;
00807 if (fHashTable) {
00808 kXR_int32 *refofs = fHashTable->Find(tag);
00809 if (*refofs > 0) {
00810
00811 if (ReadInd(*refofs, ind) < 0) {
00812 Close();
00813 return -1;
00814 }
00815 found = 1;
00816 }
00817 } else {
00818
00819 kXR_int32 indofs = header.indofs;
00820 while (indofs > 0) {
00821
00822 if (ReadInd(indofs, ind) < 0) {
00823 Close();
00824 return -1;
00825 }
00826
00827 if (strlen(ind.name) == strlen(tag)) {
00828 if (!strncmp(ind.name,tag,strlen(tag))) {
00829 found = 1;
00830 break;
00831 }
00832 }
00833
00834 indofs = ind.nxtofs;
00835 }
00836 }
00837
00838
00839 XrdSutPFEntry ent;
00840 bool changed = 0;
00841 if (found) {
00842
00843
00844 if (ind.entofs) {
00845 if (ReadEnt(ind.entofs, ent) < 0) {
00846 Close();
00847 return -1;
00848 }
00849
00850
00851 if (reset && ent.cnt != 0) {
00852 changed = 1;
00853 ent.cnt = 0;
00854 }
00855
00856
00857 if (step != 0) {
00858 changed = 1;
00859 ent.cnt += step;
00860 }
00861
00862
00863 if (changed) {
00864 ent.mtime = (kXR_int32)time(0);
00865 if (WriteEnt(ind.entofs, ent) < 0) {
00866 Close();
00867 return -1;
00868 }
00869 }
00870
00871
00872 if (cnt)
00873 *cnt = ent.cnt;
00874 }
00875 }
00876
00877
00878 Close();
00879
00880 return 0;
00881 }
00882
00883
00884 kXR_int32 XrdSutPFile::ReadEntry(const char *tag,
00885 XrdSutPFEntry &ent, int opt)
00886 {
00887
00888
00889
00890
00891
00892
00893 ent.Reset();
00894
00895
00896 if (!tag)
00897 return Err(kPFErrBadInputs,"ReadEntry");
00898
00899
00900 bool wasopen = 0;
00901 if (Open(1 &wasopen) < 0)
00902 return -1;
00903
00904
00905 XrdSutPFHeader header;
00906 if (ReadHeader(header) < 0) {
00907 if (!wasopen) Close();
00908 return -1;
00909 }
00910
00911
00912 if (fHashTable && header.itime > fHTutime) {
00913
00914 if (UpdateHashTable() < 0) {
00915 if (!wasopen) Close();
00916 return -1;
00917 }
00918 }
00919
00920
00921 XrdSutPFEntInd ind;
00922 bool found = 0;
00923 if (fHashTable) {
00924 kXR_int32 *reftmp = fHashTable->Find(tag);
00925 kXR_int32 refofs = reftmp ? *reftmp : -1;
00926 if (refofs > 0) {
00927
00928 if (ReadInd(refofs, ind) < 0) {
00929 if (!wasopen) Close();
00930 return -1;
00931 }
00932 found = 1;
00933 }
00934 } else {
00935
00936 kXR_int32 indofs = header.indofs;
00937 while (indofs > 0) {
00938
00939 if (ReadInd(indofs, ind) < 0) {
00940 if (!wasopen) Close();
00941 return -1;
00942 }
00943
00944 if (strlen(ind.name) == strlen(tag)) {
00945 if (!strncmp(ind.name,tag,strlen(tag))) {
00946 found = 1;
00947 break;
00948 }
00949 }
00950
00951 indofs = ind.nxtofs;
00952 }
00953 }
00954
00955
00956 if (!found && opt == 1) {
00957
00958
00959
00960 kXR_int32 refofs = -1;
00961 kXR_int32 nmmax = 0;
00962 kXR_int32 iofs = header.indofs;
00963 XrdOucString stag(tag);
00964 while (iofs) {
00965
00966
00967 if (ReadInd(iofs, ind) < 0) {
00968 if (!wasopen) Close();
00969 return -1;
00970 }
00971
00972
00973 if (ind.entofs > 0) {
00974 int match = stag.matches(ind.name);
00975 if (match > nmmax && ind.entofs > 0) {
00976 nmmax = match;
00977 refofs = iofs;
00978 }
00979 }
00980
00981
00982 iofs = ind.nxtofs;
00983 }
00984
00985
00986 if (refofs > 0) {
00987 if (ReadInd(refofs, ind) < 0) {
00988 if (!wasopen) Close();
00989 return -1;
00990 }
00991 found = 1;
00992 }
00993 }
00994
00995
00996 kXR_int32 nr = 0;
00997 if (found) {
00998
00999
01000 if (ind.entofs) {
01001 if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
01002 if (!wasopen) Close();
01003 return -1;
01004 }
01005
01006 ent.SetName(ind.name);
01007 }
01008 }
01009
01010
01011 if (!wasopen) Close();
01012
01013 return nr;
01014 }
01015
01016
01017 kXR_int32 XrdSutPFile::ReadEntry(kXR_int32 ofs, XrdSutPFEntry &ent)
01018 {
01019
01020
01021
01022 if (ofs <= 0)
01023 return Err(kPFErrBadInputs,"ReadEntry");
01024
01025
01026 bool wasopen = 0;
01027 if (Open(1, &wasopen) < 0)
01028 return -1;
01029
01030 kXR_int32 nr = 0;
01031
01032
01033 XrdSutPFEntInd ind;
01034 if (ReadInd(ofs, ind) < 0) {
01035 if (!wasopen) Close();
01036 return -1;
01037 }
01038
01039
01040 if ((nr = ReadEnt(ind.entofs, ent)) < 0) {
01041 if (!wasopen) Close();
01042 return -1;
01043 }
01044
01045
01046 ent.SetName(ind.name);
01047
01048
01049 if (!wasopen) Close();
01050
01051 return nr;
01052 }
01053
01054
01055 kXR_int32 XrdSutPFile::RemoveEntry(const char *tag)
01056 {
01057
01058
01059
01060
01061
01062 if (!tag || !strlen(tag))
01063 return Err(kPFErrBadInputs,"RemoveEntry");
01064
01065
01066 if (Open(1) < 0)
01067 return -1;
01068
01069
01070 XrdSutPFHeader header;
01071 if (ReadHeader(header) < 0) {
01072 Close();
01073 return -1;
01074 }
01075
01076
01077 if (fHashTable && header.itime > fHTutime) {
01078
01079 if (UpdateHashTable() < 0) {
01080 Close();
01081 return -1;
01082 }
01083 }
01084
01085
01086 XrdSutPFEntInd ind;
01087 bool found = 0;
01088 kXR_int32 indofs = -1;
01089 if (fHashTable) {
01090 kXR_int32 *indtmp = fHashTable->Find(tag);
01091 indofs = indtmp ? *indtmp : indofs;
01092 if (indofs > 0) {
01093
01094 if (ReadInd(indofs, ind) < 0) {
01095 Close();
01096 return -1;
01097 }
01098 found = 1;
01099 }
01100 } else {
01101
01102 indofs = header.indofs;
01103 while (indofs > 0) {
01104
01105 if (ReadInd(indofs, ind) < 0) {
01106 Close();
01107 return -1;
01108 }
01109
01110 if (strlen(ind.name) == strlen(tag)) {
01111 if (!strncmp(ind.name,tag,strlen(tag))) {
01112 found = 1;
01113 break;
01114 }
01115 }
01116
01117 indofs = ind.nxtofs;
01118 }
01119 }
01120
01121
01122 if (found) {
01123
01124 short status = kPFE_inactive;
01125 if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
01126 Close();
01127 return Err(kPFErrSeek,"RemoveEntry",
01128 "SEEK_SET",(const char *)&fFd);
01129 }
01130 while (write(fFd, &status, sizeof(short)) < 0 &&
01131 errno == EINTR) errno = 0;
01132
01133 if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
01134 Close();
01135 return -1;
01136 }
01137
01138 ind.entofs = 0;
01139 if (WriteInd(indofs, ind) < 0) {
01140 Close();
01141 return -1;
01142 }
01143
01144 header.jnksiz += ind.entsiz;
01145
01146 header.entries--;
01147
01148 header.ctime = (kXR_int32)time(0);
01149 header.itime = header.ctime;
01150
01151 if (WriteHeader(header) < 0) {
01152 Close();
01153 return -1;
01154 }
01155
01156
01157 Close();
01158 return 0;
01159 }
01160
01161
01162 Close();
01163
01164 return -1;
01165 }
01166
01167
01168 kXR_int32 XrdSutPFile::RemoveEntry(kXR_int32 ofs)
01169 {
01170
01171
01172
01173
01174
01175 if (ofs <= 0)
01176 return Err(kPFErrBadInputs,"RemoveEntry");
01177
01178
01179 if (Open(1) < 0)
01180 return -1;
01181
01182
01183 XrdSutPFHeader header;
01184 if (ReadHeader(header) < 0) {
01185 Close();
01186 return -1;
01187 }
01188
01189
01190 if (header.itime > fHTutime) {
01191
01192 if (UpdateHashTable() < 0) {
01193 Close();
01194 return -1;
01195 }
01196 }
01197
01198
01199 XrdSutPFEntInd ind;
01200 if (ReadInd(ofs, ind) < 0) {
01201 Close();
01202 return -1;
01203 }
01204
01205
01206 short status = kPFE_inactive;
01207 if (lseek(fFd, ind.entofs, SEEK_SET) == -1) {
01208 Close();
01209 return Err(kPFErrSeek,"RemoveEntry",
01210 "SEEK_SET",(const char *)&fFd);
01211 }
01212 while (write(fFd, &status, sizeof(short)) < 0 &&
01213 errno == EINTR) errno = 0;
01214
01215 if (Reset(ind.entofs + sizeof(short), ind.entsiz - sizeof(short)) < 0) {
01216 Close();
01217 return -1;
01218 }
01219
01220 ind.entofs = 0;
01221 if (WriteInd(ofs, ind) < 0) {
01222 Close();
01223 return -1;
01224 }
01225
01226 header.jnksiz += ind.entsiz;
01227
01228 header.entries--;
01229
01230 header.ctime = (kXR_int32)time(0);
01231 header.itime = header.ctime;
01232
01233 if (WriteHeader(header) < 0) {
01234 Close();
01235 return -1;
01236 }
01237
01238
01239 Close();
01240 return 0;
01241 }
01242
01243
01244 kXR_int32 XrdSutPFile::Reset(kXR_int32 ofs, kXR_int32 siz)
01245 {
01246
01247
01248
01249
01250 if (lseek(fFd, ofs, SEEK_SET) == -1)
01251 return Err(kPFErrSeek,"Reset",
01252 "SEEK_SET",(const char *)&fFd);
01253
01254 kXR_int32 nrs = 0;
01255
01256 while (nrs < siz) {
01257 char c = 0;
01258 while (write(fFd, &c, 1) < 0 && errno == EINTR)
01259 errno = 0;
01260 nrs++;
01261 }
01262
01263 return nrs;
01264 }
01265
01266
01267
01268 kXR_int32 XrdSutPFile::WriteInd(kXR_int32 ofs, XrdSutPFEntInd ind)
01269 {
01270
01271
01272
01273 if (fFd < 0)
01274 return Err(kPFErrFileNotOpen,"WriteInd");
01275
01276
01277 if (lseek(fFd, ofs, SEEK_SET) == -1)
01278 return Err(kPFErrSeek,"WriteInd",
01279 "SEEK_SET",(const char *)&fFd);
01280
01281
01282
01283
01284 kXR_int32 ltot = ind.Length();
01285
01286
01287 char *bout = new char[ltot];
01288 if (!bout)
01289 return Err(kPFErrOutOfMemory,"WriteInd");
01290
01291
01292 kXR_int32 lp = 0;
01293
01294 kXR_int32 lnam = strlen(ind.name);
01295 memcpy(bout+lp,&lnam,sizeof(kXR_int32));
01296 lp += sizeof(kXR_int32);
01297
01298 memcpy(bout+lp,&ind.nxtofs,sizeof(kXR_int32));
01299 lp += sizeof(kXR_int32);
01300
01301 memcpy(bout+lp,&ind.entofs,sizeof(kXR_int32));
01302 lp += sizeof(kXR_int32);
01303
01304 memcpy(bout+lp,&ind.entsiz,sizeof(kXR_int32));
01305 lp += sizeof(kXR_int32);
01306
01307 memcpy(bout+lp,ind.name,lnam);
01308 lp += lnam;
01309
01310 if (lp != ltot) {
01311 if (bout) delete[] bout;
01312 return Err(kPFErrLenMismatch,"WriteInd",
01313 (const char *)&lp, (const char *)<ot);
01314 }
01315
01316 kXR_int32 nw = 0;
01317
01318 while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
01319 errno = 0;
01320
01321 return nw;
01322 }
01323
01324
01325 kXR_int32 XrdSutPFile::WriteEnt(kXR_int32 ofs, XrdSutPFEntry ent)
01326 {
01327
01328
01329
01330 if (fFd < 0)
01331 return Err(kPFErrFileNotOpen,"WriteEnt");
01332
01333
01334 if (lseek(fFd, ofs, SEEK_SET) == -1)
01335 return Err(kPFErrSeek,"WriteEnt",
01336 "SEEK_SET",(const char *)&fFd);
01337
01338
01339
01340
01341 kXR_int32 ltot = ent.Length();
01342
01343
01344 char *bout = new char[ltot];
01345 if (!bout)
01346 return Err(kPFErrOutOfMemory,"WriteEnt");
01347
01348
01349 kXR_int32 lp = 0;
01350
01351 memcpy(bout+lp,&ent.status,sizeof(short));
01352 lp += sizeof(short);
01353
01354 memcpy(bout+lp,&ent.cnt,sizeof(short));
01355 lp += sizeof(short);
01356
01357 memcpy(bout+lp,&ent.mtime,sizeof(kXR_int32));
01358 lp += sizeof(kXR_int32);
01359
01360 memcpy(bout+lp,&ent.buf1.len,sizeof(kXR_int32));
01361 lp += sizeof(kXR_int32);
01362
01363 memcpy(bout+lp,&ent.buf2.len,sizeof(kXR_int32));
01364 lp += sizeof(kXR_int32);
01365
01366 memcpy(bout+lp,&ent.buf3.len,sizeof(kXR_int32));
01367 lp += sizeof(kXR_int32);
01368
01369 memcpy(bout+lp,&ent.buf4.len,sizeof(kXR_int32));
01370 lp += sizeof(kXR_int32);
01371 if (ent.buf1.len > 0) {
01372
01373 memcpy(bout+lp,ent.buf1.buf,ent.buf1.len);
01374 lp += ent.buf1.len;
01375 }
01376 if (ent.buf2.len > 0) {
01377
01378 memcpy(bout+lp,ent.buf2.buf,ent.buf2.len);
01379 lp += ent.buf2.len;
01380 }
01381 if (ent.buf3.len > 0) {
01382
01383 memcpy(bout+lp,ent.buf3.buf,ent.buf3.len);
01384 lp += ent.buf3.len;
01385 }
01386 if (ent.buf4.len > 0) {
01387
01388 memcpy(bout+lp,ent.buf4.buf,ent.buf4.len);
01389 lp += ent.buf4.len;
01390 }
01391
01392 if (lp != ltot) {
01393 if (bout) delete[] bout;
01394 return Err(kPFErrLenMismatch,"WriteEnt",
01395 (const char *)&lp, (const char *)<ot);
01396 }
01397
01398 kXR_int32 nw = 0;
01399
01400 while ((nw = write(fFd, bout, ltot)) < 0 && errno == EINTR)
01401 errno = 0;
01402
01403 return nw;
01404 }
01405
01406
01407 kXR_int32 XrdSutPFile::ReadHeader(XrdSutPFHeader &hd)
01408 {
01409
01410
01411
01412
01413 if (fFd < 0)
01414 return Err(kPFErrFileNotOpen,"ReadHeader");
01415
01416
01417 if (lseek(fFd, 0, SEEK_SET) == -1)
01418 return Err(kPFErrSeek,"ReadHeader",
01419 "SEEK_SET",(const char *)&fFd);
01420
01421 kXR_int32 nr = 0, nrdt = 0;
01422
01423
01424
01425 if ((nr = read(fFd,hd.fileID,kFileIDSize)) != kFileIDSize)
01426 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01427 hd.fileID[kFileIDSize-1] = 0;
01428 nrdt += nr;
01429
01430 if ((nr = read(fFd,&hd.version,sizeof(kXR_int32))) != sizeof(kXR_int32))
01431 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01432 nrdt += nr;
01433
01434 if ((nr = read(fFd,&hd.ctime,sizeof(kXR_int32))) != sizeof(kXR_int32))
01435 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01436 nrdt += nr;
01437
01438 if ((nr = read(fFd,&hd.itime,sizeof(kXR_int32))) != sizeof(kXR_int32))
01439 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01440 nrdt += nr;
01441
01442 if ((nr = read(fFd,&hd.entries,sizeof(kXR_int32))) != sizeof(kXR_int32))
01443 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01444 nrdt += nr;
01445
01446 if ((nr = read(fFd,&hd.indofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
01447 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01448 nrdt += nr;
01449
01450 if ((nr = read(fFd,&hd.jnksiz,sizeof(kXR_int32))) != sizeof(kXR_int32))
01451 return Err(kPFErrRead,"ReadHeader",(const char *)&fFd);
01452 nrdt += nr;
01453
01454 return nrdt;
01455 }
01456
01457
01458 kXR_int32 XrdSutPFile::ReadInd(kXR_int32 ofs, XrdSutPFEntInd &ind)
01459 {
01460
01461
01462
01463
01464 if (fFd < 0)
01465 return Err(kPFErrFileNotOpen,"ReadInd");
01466
01467
01468 if (lseek(fFd, ofs, SEEK_SET) == -1)
01469 return Err(kPFErrSeek,"ReadInd",
01470 "SEEK_SET",(const char *)&fFd);
01471
01472 kXR_int32 nr = 0, nrdt = 0;
01473
01474
01475
01476 kXR_int32 lnam = 0;
01477 if ((nr = read(fFd,&lnam,sizeof(kXR_int32))) != sizeof(kXR_int32))
01478 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
01479 nrdt += nr;
01480
01481 if ((nr = read(fFd,&ind.nxtofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
01482 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
01483 nrdt += nr;
01484
01485 if ((nr = read(fFd,&ind.entofs,sizeof(kXR_int32))) != sizeof(kXR_int32))
01486 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
01487 nrdt += nr;
01488
01489 if ((nr = read(fFd,&ind.entsiz,sizeof(kXR_int32))) != sizeof(kXR_int32))
01490 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
01491 nrdt += nr;
01492
01493 if (ind.name) {
01494 delete[] ind.name;
01495 ind.name = 0;
01496 }
01497 if (lnam) {
01498 ind.name = new char[lnam+1];
01499 if (ind.name) {
01500 if ((nr = read(fFd,ind.name,lnam)) != lnam)
01501 return Err(kPFErrRead,"ReadInd",(const char *)&fFd);
01502 ind.name[lnam] = 0;
01503 nrdt += nr;
01504 } else
01505 return Err(kPFErrOutOfMemory,"ReadInd");
01506 }
01507
01508 return nrdt;
01509 }
01510
01511
01512 kXR_int32 XrdSutPFile::ReadEnt(kXR_int32 ofs, XrdSutPFEntry &ent)
01513 {
01514
01515
01516
01517
01518 if (fFd < 0)
01519 return Err(kPFErrFileNotOpen,"ReadEnt");
01520
01521
01522 if (lseek(fFd, ofs, SEEK_SET) == -1)
01523 return Err(kPFErrSeek,"ReadEnt",
01524 "SEEK_SET",(const char *)&fFd);
01525
01526 kXR_int32 nr = 0, nrdt = 0;
01527
01528
01529
01530 if ((nr = read(fFd,&ent.status,sizeof(short))) != sizeof(short))
01531 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01532 nrdt += nr;
01533
01534 if ((nr = read(fFd,&ent.cnt,sizeof(short))) != sizeof(short))
01535 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01536 nrdt += nr;
01537
01538 if ((nr = read(fFd,&ent.mtime,sizeof(kXR_int32))) != sizeof(kXR_int32))
01539 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01540 nrdt += nr;
01541
01542 if ((nr = read(fFd,&ent.buf1.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
01543 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01544 nrdt += nr;
01545
01546 if ((nr = read(fFd,&ent.buf2.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
01547 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01548 nrdt += nr;
01549
01550 if ((nr = read(fFd,&ent.buf3.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
01551 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01552 nrdt += nr;
01553
01554 if ((nr = read(fFd,&ent.buf4.len,sizeof(kXR_int32))) != sizeof(kXR_int32))
01555 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01556 nrdt += nr;
01557
01558 if (ent.buf1.len) {
01559 ent.buf1.buf = new char[ent.buf1.len];
01560 if (!ent.buf1.buf)
01561 return Err(kPFErrOutOfMemory,"ReadEnt");
01562 if ((nr = read(fFd,ent.buf1.buf,ent.buf1.len)) != ent.buf1.len)
01563 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01564 nrdt += nr;
01565 }
01566
01567 if (ent.buf2.len) {
01568 ent.buf2.buf = new char[ent.buf2.len];
01569 if (!ent.buf2.buf)
01570 return Err(kPFErrOutOfMemory,"ReadEnt");
01571 if ((nr = read(fFd,ent.buf2.buf,ent.buf2.len)) != ent.buf2.len)
01572 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01573 nrdt += nr;
01574 }
01575
01576 if (ent.buf3.len) {
01577 ent.buf3.buf = new char[ent.buf3.len];
01578 if (!ent.buf3.buf)
01579 return Err(kPFErrOutOfMemory,"ReadEnt");
01580 if ((nr = read(fFd,ent.buf3.buf,ent.buf3.len)) != ent.buf3.len)
01581 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01582 nrdt += nr;
01583 }
01584
01585 if (ent.buf4.len) {
01586 ent.buf4.buf = new char[ent.buf4.len];
01587 if (!ent.buf4.buf)
01588 return Err(kPFErrOutOfMemory,"ReadEnt");
01589 if ((nr = read(fFd,ent.buf4.buf,ent.buf4.len)) != ent.buf4.len)
01590 return Err(kPFErrRead,"ReadEnt",(const char *)&fFd);
01591 nrdt += nr;
01592 }
01593
01594 return nrdt;
01595 }
01596
01597
01598 kXR_int32 XrdSutPFile::Browse(void *oout)
01599 {
01600
01601
01602
01603 if (Open(1) < 0)
01604 return -1;
01605
01606
01607 XrdSutPFHeader hdr;
01608 if (ReadHeader(hdr) < 0) {
01609 Close();
01610 return -1;
01611 }
01612
01613
01614 struct tm tst;
01615 char sctime[256] = {0};
01616 time_t ttmp = hdr.ctime;
01617 localtime_r(&ttmp,&tst);
01618 asctime_r(&tst,sctime);
01619 sctime[strlen(sctime)-1] = 0;
01620 char sitime[256] = {0};
01621 ttmp = hdr.itime;
01622 localtime_r(&ttmp,&tst);
01623 asctime_r(&tst,sitime);
01624 sitime[strlen(sitime)-1] = 0;
01625
01626
01627 FILE *out = oout ? (FILE *)oout : stdout;
01628
01629 fprintf(out,"//-----------------------------------------------------"
01630 "--------------------//\n");
01631 fprintf(out,"//\n");
01632 fprintf(out,"// File: %s\n",name);
01633 fprintf(out,"// ID: %s\n",hdr.fileID);
01634 fprintf(out,"// Version: %d\n",hdr.version);
01635 fprintf(out,"// Last change : %s (%d sec)\n",sctime,hdr.ctime);
01636 fprintf(out,"// Index change: %s (%d sec)\n",sitime,hdr.itime);
01637 fprintf(out,"//\n");
01638 fprintf(out,"// Number of Entries: %d\n",hdr.entries);
01639 fprintf(out,"// Bytes unreachable: %d\n",hdr.jnksiz);
01640 fprintf(out,"//\n");
01641
01642 if (hdr.entries > 0) {
01643
01644
01645 kXR_int32 ns = SearchSpecialEntries();
01646 if (ns > 0) {
01647
01648 kXR_int32 *sofs = new kXR_int32[ns];
01649 if (sofs) {
01650
01651 ns = SearchSpecialEntries(sofs,ns);
01652 fprintf(out,"// Special entries (%d):\n",ns);
01653 int i = 0;
01654 for (; i<ns; i++) {
01655
01656
01657 XrdSutPFEntInd ind;
01658 if (ReadInd(sofs[i], ind) < 0) {
01659 Close();
01660 return -1;
01661 }
01662
01663 if (ind.entofs) {
01664
01665 XrdSutPFEntry ent;
01666 if (ReadEnt(ind.entofs, ent) < 0) {
01667 Close();
01668 return -1;
01669 }
01670 char smt[20] = {0};
01671 XrdSutTimeString(ent.mtime,smt);
01672 char buf[2048] = {0};
01673 memset(buf,0,2048);
01674 sprintf(buf,"// #%d mod:%s",i+1,smt);
01675 sprintf(buf,"%s name:%s",buf,ind.name);
01676 fprintf(out,"%s\n",buf);
01677 sprintf(buf,"// buf");
01678 if (ent.cnt == 1) {
01679 if (ent.buf1.len && ent.buf1.buf)
01680 sprintf(buf,"%s: %.*s",buf,ent.buf1.len,ent.buf1.buf);
01681 if (ent.buf2.len && ent.buf2.buf)
01682 sprintf(buf,"%s: %.*s",buf,ent.buf2.len,ent.buf2.buf);
01683 if (ent.buf3.len && ent.buf3.buf)
01684 sprintf(buf,"%s: %.*s",buf,ent.buf3.len,ent.buf3.buf);
01685 if (ent.buf4.len && ent.buf4.buf)
01686 sprintf(buf,"%s: %.*s",buf,ent.buf4.len,ent.buf4.buf);
01687 } else {
01688 sprintf(buf,"%s:%d:%d:%d:%d",buf,
01689 ent.buf1.len,ent.buf2.len,ent.buf3.len,
01690 ent.buf4.len);
01691 sprintf(buf,"%s (protected)",buf);
01692 }
01693 fprintf(out,"%s\n",buf);
01694 }
01695 }
01696 fprintf(out,"//\n");
01697 delete[] sofs;
01698 }
01699 }
01700
01701 if (hdr.entries > ns)
01702 fprintf(out,"// Normal entries (%d):\n",hdr.entries-ns);
01703
01704 kXR_int32 nn = 0;
01705 kXR_int32 nxtofs = hdr.indofs;
01706 while (nxtofs) {
01707
01708
01709 XrdSutPFEntInd ind;
01710 if (ReadInd(nxtofs, ind) < 0) {
01711 Close();
01712 return -3;
01713 }
01714
01715 if (ind.entofs) {
01716
01717 XrdSutPFEntry ent;
01718 if (ReadEnt(ind.entofs, ent) < 0) {
01719 Close();
01720 return -4;
01721 }
01722 if (ent.status != kPFE_special) {
01723 char smt[20] = {0};
01724 XrdSutTimeString(ent.mtime,smt);
01725
01726 nn++;
01727 fprintf(out,
01728 "// #:%d st:%d cn:%d buf:%d,%d,%d,%d mod:%s name:%s\n",
01729 nn,ent.status,ent.cnt,ent.buf1.len,ent.buf2.len,ent.buf3.len,
01730 ent.buf4.len,smt,ind.name);
01731 }
01732 }
01733
01734
01735 nxtofs = ind.nxtofs;
01736 }
01737 fprintf(out,"//\n");
01738 }
01739 fprintf(out,"//-----------------------------------------------------"
01740 "--------------------//\n");
01741
01742
01743 Close();
01744
01745 return 0;
01746 }
01747
01748
01749 kXR_int32 XrdSutPFile::Trim(const char *fbak)
01750 {
01751
01752
01753
01754 EPNAME("PFile::Trim");
01755
01756
01757 XrdSutPFHeader header;
01758 if (RetrieveHeader(header) < 0)
01759 return -1;
01760 if (header.jnksiz <= 0) {
01761 DEBUG("nothing to trim - return ");
01762 return -1;
01763 }
01764
01765
01766 char *nbak = (char *)fbak;
01767 if (!nbak) {
01768
01769 nbak = new char[strlen(name)+5];
01770 if (!nbak)
01771 return Err(kPFErrOutOfMemory,"Trim");
01772 sprintf(nbak,"%s.bak",name);
01773 DEBUG("backup file: "<<nbak);
01774 }
01775
01776
01777 if (rename(name,nbak) == -1)
01778 return Err(kPFErrFileRename,"Trim",name,nbak);
01779
01780
01781 int fdnew = Open(1);
01782 if (fdnew < 0)
01783 return -1;
01784
01785
01786 int fdbck = Open(1,0,nbak);
01787 if (fdbck < 0) {
01788 Close();
01789 return -1;
01790 }
01791
01792
01793 fFd = fdbck;
01794 if (ReadHeader(header) < 0) {
01795 Close(fdnew); Close(fdbck);
01796 return -1;
01797 }
01798
01799
01800 fFd = fdnew;
01801 if (WriteHeader(header) < 0) {
01802 Close(fdnew); Close(fdbck);
01803 return -1;
01804 }
01805 kXR_int32 wrofs = lseek(fdnew, 0, SEEK_CUR);
01806 if (wrofs == -1) {
01807 Close(fdnew); Close(fdbck);
01808 return Err(kPFErrSeek,"Trim",
01809 "SEEK_CUR",(const char *)&fdnew);
01810 }
01811
01812
01813 bool firstind = 1;
01814 XrdSutPFEntInd ind, indlast;
01815 XrdSutPFEntry ent;
01816
01817 kXR_int32 nxtofs = header.indofs;
01818 kXR_int32 lastofs = nxtofs;
01819
01820 while (nxtofs) {
01821
01822
01823 fFd = fdbck;
01824 if (ReadInd(nxtofs,ind) < 0) {
01825 Close(fdnew); Close(fdbck);
01826 return -1;
01827 }
01828
01829
01830 nxtofs = ind.nxtofs;
01831
01832
01833 if (ind.entofs > 0) {
01834 fFd = fdbck;
01835 if (ReadEnt(ind.entofs,ent) < 0) {
01836 Close(fdnew); Close(fdbck);
01837 return -1;
01838 }
01839
01840 ind.entofs = wrofs;
01841
01842
01843 fFd = fdnew;
01844 if (WriteEnt(wrofs,ent) < 0) {
01845 Close(fdnew); Close(fdbck);
01846 return -1;
01847 }
01848
01849
01850 if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
01851 Close(fdnew); Close(fdbck);
01852 return Err(kPFErrSeek,"Trim",
01853 "SEEK_CUR",(const char *)&fdnew);
01854 }
01855
01856 if (firstind) {
01857
01858 header.indofs = wrofs;
01859 firstind = 0;
01860 } else {
01861
01862 indlast.nxtofs = wrofs;
01863 fFd = fdnew;
01864 if (WriteInd(lastofs,indlast) < 0) {
01865 Close(fdnew); Close(fdbck);
01866 return -1;
01867 }
01868 }
01869
01870
01871 indlast = ind;
01872 lastofs = wrofs;
01873
01874
01875 ind.nxtofs = 0;
01876
01877
01878 fFd = fdnew;
01879 if (WriteInd(wrofs,ind) < 0) {
01880 Close(fdnew); Close(fdbck);
01881 return -1;
01882 }
01883
01884
01885 if ((wrofs = lseek(fdnew, 0, SEEK_CUR)) == -1) {
01886 Close(fdnew); Close(fdbck);
01887 return Err(kPFErrSeek,"Trim",
01888 "SEEK_CUR",(const char *)&fdnew);
01889 }
01890 }
01891 }
01892
01893
01894 Close(fdbck);
01895 fFd = fdnew;
01896
01897
01898 header.ctime = (kXR_int32)time(0);
01899 header.itime = header.ctime;
01900 header.jnksiz = 0;
01901
01902
01903 if (WriteHeader(header) < 0) {
01904 Close();;
01905 return -1;
01906 }
01907
01908
01909 Close();
01910
01911 return 0;
01912 }
01913
01914
01915 kXR_int32 XrdSutPFile::UpdateHashTable(bool force)
01916 {
01917
01918
01919
01920
01921
01922
01923 if (fFd < 0)
01924 return Err(kPFErrFileNotOpen,"UpdateHashTable");
01925
01926
01927 XrdSutPFHeader header;
01928 if (ReadHeader(header) < 0)
01929 return -1;
01930
01931
01932 if (!force && header.itime < fHTutime)
01933 return 0;
01934
01935
01936 if (fHashTable)
01937 fHashTable->Purge();
01938 else
01939 fHashTable = new XrdOucHash<kXR_int32>;
01940
01941 if (!fHashTable)
01942 return Err(kPFErrOutOfMemory,"UpdateHashTable");
01943
01944
01945 kXR_int32 ne = 0;
01946 if (header.entries > 0) {
01947 XrdSutPFEntInd ind;
01948 kXR_int32 nxtofs = header.indofs;
01949 while (nxtofs > 0) {
01950 if (ReadInd(nxtofs, ind) < 0)
01951 return -1;
01952 ne++;
01953
01954 kXR_int32 *key = new kXR_int32(nxtofs);
01955 fHashTable->Add(ind.name,key);
01956
01957 nxtofs = ind.nxtofs;
01958 }
01959 }
01960
01961
01962 fHTutime = (kXR_int32)time(0);
01963
01964 return ne;
01965 }
01966
01967
01968 kXR_int32 XrdSutPFile::RemoveEntries(const char *tag, char opt)
01969 {
01970
01971
01972
01973
01974
01975 EPNAME("PFile::RemoveEntries");
01976
01977
01978
01979 int nm = SearchEntries(tag,opt);
01980 if (nm) {
01981 DEBUG("found "<<nm<<" entries for tag '"<<tag<<"'");
01982
01983
01984 int *ofs = new int[nm];
01985
01986
01987 SearchEntries(tag,0,ofs,nm);
01988
01989
01990 int i = 0;
01991 for (; i < nm ; i++) {
01992 if (RemoveEntry(ofs[i]) == 0) {
01993 DEBUG("entry for tag '"<<tag<<"' removed from file");
01994 } else {
01995 DEBUG("entry for tag '"<<tag<<"' not found in file");
01996 }
01997 }
01998 } else {
01999 DEBUG("no entry for tag '"<<tag<<"' found in file: "<<Name());
02000 }
02001
02002 return nm;
02003 }
02004
02005
02006 kXR_int32 XrdSutPFile::SearchEntries(const char *tag, char opt,
02007 kXR_int32 *ofs, kXR_int32 nofs)
02008 {
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022 if (!tag)
02023 return Err(kPFErrBadInputs,"SearchEntries");
02024
02025
02026 bool wasopen = 0;
02027 if (Open(1,&wasopen) < 0)
02028 return -1;
02029
02030
02031 XrdSutPFHeader header;
02032 if (ReadHeader(header) < 0) {
02033 if (!wasopen) Close();
02034 return -1;
02035 }
02036
02037
02038 kXR_int32 indofs = header.indofs;
02039
02040
02041 kXR_int32 no = 0;
02042 XrdOucString smatch;
02043 if (opt == 1)
02044 smatch.assign(tag, 0);
02045 while (indofs) {
02046
02047
02048 XrdSutPFEntInd ind;
02049 if (ReadInd(indofs, ind) < 0) {
02050 if (!wasopen) Close();
02051 return -1;
02052 }
02053
02054
02055 int match = 0;
02056 if (opt == 0) {
02057 if (!strncmp(ind.name,tag,strlen(tag)))
02058 match = 1;
02059 } else if (opt == 1) {
02060 match = smatch.matches(ind.name);
02061 } else if (opt == 2) {
02062 smatch.assign(ind.name, 0);
02063 match = smatch.matches(tag);
02064 }
02065
02066 if (match > 0 && ind.entofs > 0) {
02067 no++;
02068 if (ofs) {
02069 ofs[no-1] = indofs;
02070 if (no == nofs) {
02071
02072 break;
02073 }
02074 }
02075 }
02076
02077
02078 indofs = ind.nxtofs;
02079 }
02080
02081
02082 if (!wasopen) Close();
02083
02084 return no;
02085 }
02086
02087
02088 kXR_int32 XrdSutPFile::SearchSpecialEntries(kXR_int32 *ofs,
02089 kXR_int32 nofs)
02090 {
02091
02092
02093
02094
02095
02096
02097
02098 bool wasopen = 0;
02099 if (Open(1,&wasopen) < 0)
02100 return -1;
02101
02102
02103 XrdSutPFHeader header;
02104 if (ReadHeader(header) < 0) {
02105 if (!wasopen) Close();
02106 return -1;
02107 }
02108
02109
02110 kXR_int32 indofs = header.indofs;
02111
02112
02113 kXR_int32 no = 0;
02114 while (indofs) {
02115
02116
02117 XrdSutPFEntInd ind;
02118 if (ReadInd(indofs, ind) < 0) {
02119 if (!wasopen) Close();
02120 return -1;
02121 }
02122
02123
02124 if (ind.entofs > 0) {
02125
02126
02127 XrdSutPFEntry ent;
02128 if (ReadEnt(ind.entofs, ent) < 0) {
02129 if (!wasopen) Close();
02130 return -1;
02131 }
02132
02133 if (ent.status == kPFE_special) {
02134
02135 no++;
02136 if (ofs) {
02137 ofs[no-1] = indofs;
02138 if (no == nofs) {
02139
02140 break;
02141 }
02142 }
02143 }
02144 }
02145
02146
02147 indofs = ind.nxtofs;
02148 }
02149
02150
02151 if (!wasopen) Close();
02152
02153 return no;
02154 }
02155
02156
02157 kXR_int32 XrdSutPFile::Err(kXR_int32 code, const char *loc,
02158 const char *em1, const char *em2)
02159 {
02160
02161
02162 EPNAME("PFile::Err");
02163
02164 char buf[XrdSutMAXBUF];
02165 int fd = 0, lp = 0, lt = 0;
02166
02167
02168 fError = code;
02169
02170
02171 char *errbuf = strerror(errno);
02172 switch (code) {
02173 case kPFErrBadInputs:
02174 snprintf(buf,XrdSutMAXBUF,
02175 "XrdSutPFile::%s: bad input arguments",loc);
02176 break;
02177 case kPFErrFileAlreadyOpen:
02178 snprintf(buf,XrdSutMAXBUF,
02179 "XrdSutPFile::%s: file already open"
02180 " in incompatible mode",loc);
02181 break;
02182 case kPFErrNoFile:
02183 snprintf(buf,XrdSutMAXBUF,
02184 "XrdSutPFile::%s: file %s does not exists",
02185 loc,em1);
02186 break;
02187 case kPFErrFileRename:
02188 snprintf(buf,XrdSutMAXBUF,
02189 "XrdSutPFile::%s: error renaming file %s to %s"
02190 " (%s)",loc,em1,em2,errbuf);
02191 break;
02192 case kPFErrStat:
02193 snprintf(buf,XrdSutMAXBUF,
02194 "XrdSutPFile::%s: cannot file %s (%s)",
02195 loc,em1,errbuf);
02196 break;
02197 case kPFErrFileOpen:
02198 snprintf(buf,XrdSutMAXBUF,
02199 "XrdSutPFile::%s: cannot open file %s (%s)",
02200 loc,em1,errbuf);
02201 break;
02202 case kPFErrFileNotOpen:
02203 snprintf(buf,XrdSutMAXBUF,
02204 "XrdSutPFile::%s: file is not open", loc);
02205 break;
02206 case kPFErrLocking:
02207 fd = *((int *)em1);
02208 snprintf(buf,XrdSutMAXBUF,
02209 "XrdSutPFile::%s: cannot lock file descriptor %d (%s)",
02210 loc,fd,errbuf);
02211 break;
02212 case kPFErrUnlocking:
02213 fd = *((int *)em1);
02214 snprintf(buf,XrdSutMAXBUF,
02215 "XrdSutPFile::%s: cannot unlock file descriptor %d (%s)",
02216 loc,fd,errbuf);
02217 break;
02218 case kPFErrFileLocked:
02219 fd = *((int *)em2);
02220 snprintf(buf,XrdSutMAXBUF,
02221 "XrdSutPFile::%s: file %s is locked by process %d",
02222 loc,em1,fd);
02223 break;
02224 case kPFErrSeek:
02225 fd = *((int *)em2);
02226 snprintf(buf,XrdSutMAXBUF,
02227 "XrdSutPFile::%s: lseek %s error on descriptor %d (%s)",
02228 loc,em1,fd,errbuf);
02229 break;
02230 case kPFErrRead:
02231 fd = *((int *)em1);
02232 snprintf(buf,XrdSutMAXBUF,
02233 "XrdSutPFile::%s: read error on descriptor %d (%s)",
02234 loc,fd,errbuf);
02235 break;
02236 case kPFErrOutOfMemory:
02237 snprintf(buf,XrdSutMAXBUF,
02238 "XrdSutPFile::%s: out of memory (%s)",
02239 loc,errbuf);
02240 break;
02241 case kPFErrLenMismatch:
02242 lp = *((int *)em1);
02243 lt = *((int *)em2);
02244 snprintf(buf,XrdSutMAXBUF,
02245 "XrdSutPFile::%s: length mismatch: %d (expected: %d)",
02246 loc,lp,lt);
02247 break;
02248 case kPFErrBadOp:
02249 snprintf(buf,XrdSutMAXBUF,
02250 "XrdSutPFile::%s: bad option: %s", loc,em1);
02251 break;
02252 default:
02253 DEBUG("unknown error code: "<<code);
02254 }
02255
02256
02257 DEBUG(buf);
02258
02259
02260 fErrStr = buf;
02261
02262 return -1;
02263 }