00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "TDCacheFile.h"
00028 #include "TError.h"
00029 #include "TSystem.h"
00030 #include "TROOT.h"
00031
00032 #include <cstdlib>
00033 #include <errno.h>
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036
00037 #include <dcap.h>
00038 #ifndef R__WIN32
00039 #include <unistd.h>
00040 #if defined(R__SUN) || defined(R__SGI) || defined(R__HPUX) || \
00041 defined(R__AIX) || defined(R__LINUX) || defined(R__SOLARIS) || \
00042 defined(R__ALPHA) || defined(R__HIUX) || defined(R__FBSD) || \
00043 defined(R__MACOSX) || defined(R__HURD) || defined(R__OBSD)
00044 #define HAS_DIRENT
00045 #endif
00046 #endif
00047
00048 #ifdef HAS_DIRENT
00049 #include <dirent.h>
00050 #endif
00051
00052 static const char* const DCACHE_PREFIX = "dcache:";
00053 static const size_t DCACHE_PREFIX_LEN = strlen(DCACHE_PREFIX);
00054 static const char* const DCAP_PREFIX = "dcap:";
00055 static const size_t DCAP_PREFIX_LEN = strlen(DCAP_PREFIX);
00056
00057
00058 ClassImp(TDCacheFile)
00059
00060
00061 TDCacheFile::TDCacheFile(const char *path, Option_t *option,
00062 const char *ftitle, Int_t compress):
00063 TFile(path, "NET", ftitle, compress)
00064 {
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 TString pathString = GetDcapPath(path);
00076 path = pathString.Data();
00077
00078 fOption = option;
00079 fOption.ToUpper();
00080 fStatCached = kFALSE;
00081
00082 if (fOption == "NEW")
00083 fOption = "CREATE";
00084
00085 Bool_t create = (fOption == "CREATE") ? kTRUE : kFALSE;
00086 Bool_t recreate = (fOption == "RECREATE") ? kTRUE : kFALSE;
00087 Bool_t update = (fOption == "UPDATE") ? kTRUE : kFALSE;
00088 Bool_t read = (fOption == "READ") ? kTRUE : kFALSE;
00089 if (!create && !recreate && !update && !read) {
00090 read = kTRUE;
00091 fOption = "READ";
00092 }
00093
00094 TString stmp;
00095 TString stmp2;
00096 const char *fname;
00097 const char *fnameWithPrefix;
00098
00099 if (!strncmp(path, DCAP_PREFIX, DCAP_PREFIX_LEN)) {
00100 fnameWithPrefix = fname = path;
00101 } else {
00102
00103 char *tname;
00104 if ((tname = gSystem->ExpandPathName(path))) {
00105 stmp = tname;
00106 stmp2 = DCACHE_PREFIX;
00107 stmp2 += tname;
00108 delete [] tname;
00109 fname = stmp;
00110 fnameWithPrefix = stmp2;
00111 } else {
00112 Error("TDCacheFile", "error expanding path %s", path);
00113 goto zombie;
00114 }
00115 }
00116
00117 if (recreate) {
00118 if (!gSystem->AccessPathName(fnameWithPrefix, kFileExists))
00119 dc_unlink(fname);
00120 recreate = kFALSE;
00121 create = kTRUE;
00122 fOption = "CREATE";
00123 }
00124 if (create && !gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
00125 Error("TDCacheFile", "file %s already exists", fname);
00126 goto zombie;
00127 }
00128 if (update) {
00129 if (gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
00130 update = kFALSE;
00131 create = kTRUE;
00132 }
00133 if (update && gSystem->AccessPathName(fnameWithPrefix, kWritePermission)) {
00134 Error("TDCacheFile", "no write permission, could not open file %s", fname);
00135 goto zombie;
00136 }
00137 }
00138
00139
00140 fRealName = fname;
00141
00142 if (create || update) {
00143 #ifndef WIN32
00144 fD = SysOpen(fname, O_RDWR | O_CREAT, 0644);
00145 #else
00146 fD = SysOpen(fname, O_RDWR | O_CREAT | O_BINARY, S_IREAD | S_IWRITE);
00147 #endif
00148 if (fD == -1) {
00149 SysError("TDCacheFile", "file %s can not be opened", fname);
00150 goto zombie;
00151 }
00152 fWritable = kTRUE;
00153 } else {
00154 #ifndef WIN32
00155 fD = SysOpen(fname, O_RDONLY, 0644);
00156 #else
00157 fD = SysOpen(fname, O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
00158 #endif
00159 if (fD == -1) {
00160 if (gSystem->AccessPathName(fnameWithPrefix, kFileExists)) {
00161 Error("TDCacheFile", "file %s does not exist", fname);
00162 goto zombie;
00163 }
00164 if (gSystem->AccessPathName(fnameWithPrefix, kReadPermission)) {
00165 Error("TDCacheFile", "no read permission, could not open file %s", fname);
00166 goto zombie;
00167 }
00168 SysError("TDCacheFile", "file %s can not be opened for reading", fname);
00169 goto zombie;
00170 }
00171 fWritable = kFALSE;
00172 }
00173
00174
00175
00176
00177 if (read) {
00178 int dcache_RAHEAD_SIZE = RAHEAD_BUFFER_SIZE;
00179 const char *DCACHE_RA_BUFFER = gSystem->Getenv("DCACHE_RA_BUFFER");
00180 if (DCACHE_RA_BUFFER) {
00181 int ra_buffer = atoi(DCACHE_RA_BUFFER);
00182 dcache_RAHEAD_SIZE = ra_buffer<=0 ? dcache_RAHEAD_SIZE : ra_buffer;
00183 }
00184 dc_setBufferSize(fD, dcache_RAHEAD_SIZE);
00185 } else {
00186 dc_noBuffering(fD);
00187 }
00188
00189 Init(create);
00190
00191 return;
00192
00193 zombie:
00194
00195 MakeZombie();
00196 gDirectory = gROOT;
00197 }
00198
00199
00200 TDCacheFile::~TDCacheFile()
00201 {
00202
00203
00204 Close();
00205 }
00206
00207
00208 Bool_t TDCacheFile::ReadBuffer(char *buf, Int_t len)
00209 {
00210
00211
00212
00213 Int_t st;
00214 if ((st = ReadBufferViaCache(buf, len))) {
00215 if (st == 2)
00216 return kTRUE;
00217 return kFALSE;
00218 }
00219
00220 return TFile::ReadBuffer(buf, len);
00221 }
00222
00223
00224 Bool_t TDCacheFile::ReadBuffer(char *buf, Long64_t pos, Int_t len)
00225 {
00226
00227
00228
00229 SetOffset(pos);
00230 Int_t st;
00231 if ((st = ReadBufferViaCache(buf, len))) {
00232 if (st == 2)
00233 return kTRUE;
00234 return kFALSE;
00235 }
00236
00237 return TFile::ReadBuffer(buf, pos, len);
00238 }
00239
00240
00241 Bool_t TDCacheFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
00242 {
00243
00244
00245
00246
00247
00248
00249 #ifdef _IOVEC2_
00250
00251 iovec2 *vector;
00252
00253 vector = (iovec2 *)malloc(sizeof(iovec2)*nbuf);
00254
00255 Int_t total_len = 0;
00256 for (Int_t i = 0; i < nbuf; i++) {
00257 vector[i].buf = &buf[total_len];
00258 vector[i].offset = pos[i] + fArchiveOffset;
00259 vector[i].len = len[i];
00260 total_len += len[i];
00261 }
00262
00263 Int_t rc = dc_readv2(fD, vector, nbuf);
00264 free(vector);
00265
00266 if (rc == 0) {
00267 fBytesRead += total_len;
00268 SetFileBytesRead(GetFileBytesRead() + total_len);
00269 return kFALSE;
00270 }
00271
00272 #endif
00273
00274
00275
00276 Int_t k = 0;
00277 Bool_t result = kTRUE;
00278 TFileCacheRead *old = fCacheRead;
00279 fCacheRead = 0;
00280
00281 Long64_t low = pos[0];
00282 Long64_t high = pos[nbuf-1] + len[nbuf-1] - pos[0];
00283
00284 Long64_t total = 0;
00285 for(Int_t j=0; j < nbuf; j++) {
00286 total += len[j];
00287 }
00288
00289 if ( high / total < 10 ) {
00290
00291 char *temp = new char[high];
00292 Seek(low);
00293 result = ReadBuffer(temp,high);
00294
00295 if (result==0) {
00296 for (Int_t i = 0; i < nbuf; i++) {
00297 memcpy(&buf[k], &(temp[pos[i]-pos[0]]), len[i]);
00298 k += len[i];
00299 }
00300 }
00301
00302 delete [] temp;
00303
00304 } else {
00305
00306 for (Int_t i = 0; i < nbuf; i++) {
00307 Seek(pos[i]);
00308 result = ReadBuffer(&buf[k], len[i]);
00309 if (result) break;
00310 k += len[i];
00311 }
00312
00313 }
00314
00315 fCacheRead = old;
00316 return result;
00317 }
00318
00319
00320 Bool_t TDCacheFile::WriteBuffer(const char *buf, Int_t len)
00321 {
00322
00323
00324
00325 if (!IsOpen() || !fWritable) return kTRUE;
00326
00327 Int_t st;
00328 if ((st = WriteBufferViaCache(buf, len))) {
00329 if (st == 2)
00330 return kTRUE;
00331 return kFALSE;
00332 }
00333
00334 return TFile::WriteBuffer(buf, len);
00335 }
00336
00337
00338 Bool_t TDCacheFile::Stage(const char *path, UInt_t after, const char *location)
00339 {
00340
00341
00342 TString pathString = GetDcapPath(path);
00343 path = pathString.Data();
00344
00345 dc_errno = 0;
00346
00347 if (dc_stage(path, after, location) == 0)
00348 return kTRUE;
00349
00350 if (dc_errno != 0)
00351 gSystem->SetErrorStr(dc_strerror(dc_errno));
00352
00353 return kFALSE;
00354 }
00355
00356
00357 Bool_t TDCacheFile::CheckFile(const char *path, const char *location)
00358 {
00359
00360
00361
00362
00363 TString pathString = GetDcapPath(path);
00364 path = pathString.Data();
00365
00366 dc_errno = 0;
00367
00368 if (dc_check(path, location) == 0)
00369 return kTRUE;
00370
00371 if (dc_errno != 0)
00372 gSystem->SetErrorStr(dc_strerror(dc_errno));
00373
00374 return kFALSE;
00375 }
00376
00377
00378 void TDCacheFile::SetOpenTimeout(UInt_t n)
00379 {
00380
00381
00382 dc_setOpenTimeout(n);
00383 }
00384
00385
00386 void TDCacheFile::SetOnError(OnErrorAction a)
00387 {
00388
00389
00390 dc_setOnError(a);
00391 }
00392
00393
00394 void TDCacheFile::SetReplyHostName(const char *host_name)
00395 {
00396
00397
00398 dc_setReplyHostName((char*)host_name);
00399 }
00400
00401
00402 const char *TDCacheFile::GetDcapVersion()
00403 {
00404
00405
00406 return getDcapVersion();
00407 }
00408
00409
00410 Int_t TDCacheFile::SysOpen(const char *pathname, Int_t flags, UInt_t mode)
00411 {
00412
00413
00414
00415
00416
00417
00418
00419 dc_setClientActive();
00420
00421 dc_errno = 0;
00422
00423 Int_t rc = dc_open(pathname, flags, (Int_t) mode);
00424
00425 if (rc < 0) {
00426 if (dc_errno != 0)
00427 gSystem->SetErrorStr(dc_strerror(dc_errno));
00428 }
00429
00430 return rc;
00431 }
00432
00433
00434 Int_t TDCacheFile::SysClose(Int_t fd)
00435 {
00436
00437
00438 dc_errno = 0;
00439
00440 Int_t rc = dc_close(fd);
00441
00442 if (rc < 0) {
00443 if (dc_errno != 0)
00444 gSystem->SetErrorStr(dc_strerror(dc_errno));
00445 }
00446
00447 return rc;
00448 }
00449
00450
00451 Int_t TDCacheFile::SysRead(Int_t fd, void *buf, Int_t len)
00452 {
00453
00454
00455 dc_errno = 0;
00456
00457 Int_t rc = dc_read(fd, buf, len);
00458
00459 if (rc < 0) {
00460 if (dc_errno != 0)
00461 gSystem->SetErrorStr(dc_strerror(dc_errno));
00462 }
00463
00464 return rc;
00465 }
00466
00467
00468 Int_t TDCacheFile::SysWrite(Int_t fd, const void *buf, Int_t len)
00469 {
00470
00471
00472 dc_errno = 0;
00473
00474 Int_t rc = dc_write(fd, (char *)buf, len);
00475
00476 if (rc < 0) {
00477 if (dc_errno != 0)
00478 gSystem->SetErrorStr(dc_strerror(dc_errno));
00479 }
00480
00481 return rc;
00482 }
00483
00484
00485 Long64_t TDCacheFile::SysSeek(Int_t fd, Long64_t offset, Int_t whence)
00486 {
00487
00488
00489 dc_errno = 0;
00490
00491 Long64_t rc = dc_lseek64(fd, offset, whence);
00492
00493 if (rc < 0) {
00494 if (dc_errno != 0)
00495 gSystem->SetErrorStr(dc_strerror(dc_errno));
00496 }
00497
00498 return rc;
00499 }
00500
00501
00502 Int_t TDCacheFile::SysSync(Int_t fd)
00503 {
00504
00505
00506
00507
00508 Int_t rc;
00509 dc_errno = 0;
00510
00511 rc = dc_fsync(fd);
00512 if (rc < 0) {
00513 if (dc_errno != 0)
00514 gSystem->SetErrorStr(dc_strerror(dc_errno));
00515 }
00516
00517 return rc;
00518 }
00519
00520
00521 Int_t TDCacheFile::SysStat(Int_t, Long_t *id, Long64_t *size,
00522 Long_t *flags, Long_t *modtime)
00523 {
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537 struct stat64 & statbuf = fStatBuffer;
00538
00539 if (fOption != "READ" || !fStatCached) {
00540
00541
00542
00543 const char *path = GetName();
00544 TString pathString = GetDcapPath(path);
00545 path = pathString.Data();
00546
00547 if (path && (dc_stat64(path, &statbuf) >= 0)) {
00548 fStatCached = kTRUE;
00549 }
00550 }
00551
00552 if (fStatCached) {
00553 if (id)
00554 *id = (statbuf.st_dev << 24) + statbuf.st_ino;
00555 if (size)
00556 *size = statbuf.st_size;
00557 if (modtime)
00558 *modtime = statbuf.st_mtime;
00559 if (flags) {
00560 *flags = 0;
00561 if (statbuf.st_mode & ((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
00562 *flags |= 1;
00563 if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
00564 *flags |= 2;
00565 if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
00566 (statbuf.st_mode & S_IFMT) != S_IFDIR)
00567 *flags |= 4;
00568 }
00569 return 0;
00570 }
00571 return 1;
00572 }
00573
00574
00575 void TDCacheFile::ResetErrno() const
00576 {
00577
00578
00579 dc_errno = 0;
00580 TSystem::ResetErrno();
00581 }
00582
00583
00584 TString TDCacheFile::GetDcapPath(const char *path)
00585 {
00586
00587
00588
00589
00590
00591 while (!strncmp(path, DCACHE_PREFIX, DCACHE_PREFIX_LEN)) {
00592 path += DCACHE_PREFIX_LEN;
00593 }
00594
00595 TUrl url(path);
00596 TString pathString(url.GetUrl());
00597
00598
00599 if(!strncmp(url.GetProtocol(), "file", 4) || !strcmp(url.GetHost(),"")){
00600 pathString = url.GetFile();
00601 }
00602
00603 return pathString;
00604 }
00605
00606
00607
00608 TDCacheSystem::TDCacheSystem() : TSystem("-DCache", "DCache Helper System")
00609 {
00610
00611
00612
00613 SetName("DCache");
00614
00615 fDirp = 0;
00616 }
00617
00618
00619 int TDCacheSystem::MakeDirectory(const char *path)
00620 {
00621
00622
00623 Int_t rc;
00624 dc_errno = 0;
00625 TString pathString = TDCacheFile::GetDcapPath(path);
00626 path = pathString.Data();
00627
00628 rc = dc_mkdir(path, 0755);
00629 if (rc < 0) {
00630 if (dc_errno != 0)
00631 gSystem->SetErrorStr(dc_strerror(dc_errno));
00632 }
00633
00634 return rc;
00635 }
00636
00637
00638 void *TDCacheSystem::OpenDirectory(const char *path)
00639 {
00640
00641
00642 dc_errno = 0;
00643 TString pathString = TDCacheFile::GetDcapPath(path);
00644 path = pathString.Data();
00645
00646 fDirp = dc_opendir(path);
00647 if (fDirp == 0) {
00648 if (dc_errno != 0)
00649 gSystem->SetErrorStr(dc_strerror(dc_errno));
00650 }
00651
00652 return fDirp;
00653 }
00654
00655
00656 void TDCacheSystem::FreeDirectory(void * dirp)
00657 {
00658
00659
00660 Int_t rc;
00661 dc_errno = 0;
00662
00663 rc = dc_closedir((DIR *)dirp);
00664 if (rc < 0) {
00665 if (dc_errno != 0)
00666 gSystem->SetErrorStr(dc_strerror(dc_errno));
00667 }
00668
00669 fDirp = 0;
00670 return;
00671 }
00672
00673
00674 const char *TDCacheSystem::GetDirEntry(void * dirp)
00675 {
00676
00677
00678 struct dirent *ent;
00679 dc_errno = 0;
00680
00681 ent = dc_readdir((DIR *)dirp);
00682 if (ent == 0) {
00683 if (dc_errno != 0)
00684 gSystem->SetErrorStr(dc_strerror(dc_errno));
00685 }
00686
00687 return !ent ? 0 : ent->d_name;
00688 }
00689
00690
00691 Bool_t TDCacheSystem::AccessPathName(const char *path, EAccessMode mode)
00692 {
00693
00694
00695
00696
00697 TString pathString = TDCacheFile::GetDcapPath(path);
00698 path = pathString.Data();
00699
00700 return dc_access(path, mode);
00701 }
00702
00703
00704 int TDCacheSystem::GetPathInfo(const char *path, FileStat_t &buf)
00705 {
00706
00707
00708
00709
00710
00711 TString pathString = TDCacheFile::GetDcapPath(path);
00712 path = pathString.Data();
00713
00714 struct stat64 sbuf;
00715
00716 if (path && (dc_stat64(path, &sbuf) >= 0)) {
00717
00718 buf.fDev = sbuf.st_dev;
00719 buf.fIno = sbuf.st_ino;
00720 buf.fMode = sbuf.st_mode;
00721 buf.fUid = sbuf.st_uid;
00722 buf.fGid = sbuf.st_gid;
00723 buf.fSize = sbuf.st_size;
00724 buf.fMtime = sbuf.st_mtime;
00725 buf.fIsLink = kFALSE;
00726
00727 return 0;
00728 }
00729 return 1;
00730 }