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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "Bytes.h"
00046
00047 #include "TError.h"
00048 #include "TEnv.h"
00049 #include "TSocket.h"
00050 #include "TXNetFile.h"
00051 #include "TROOT.h"
00052 #include "TVirtualMonitoring.h"
00053 #include "TFileStager.h"
00054 #include "TFileCacheRead.h"
00055 #include "TTimeStamp.h"
00056 #include "TVirtualPerfStats.h"
00057
00058 #include <XrdClient/XrdClient.hh>
00059 #include <XrdClient/XrdClientConst.hh>
00060 #include <XrdClient/XrdClientEnv.hh>
00061 #include <XProtocol/XProtocol.hh>
00062 #ifdef OLDXRDOUC
00063 # include "XrdOuc/XrdOucPthread.hh"
00064 #else
00065 # include "XrdSys/XrdSysPthread.hh"
00066 #endif
00067
00068 ClassImp(TXNetFile);
00069
00070 Bool_t TXNetFile::fgInitDone = kFALSE;
00071 Bool_t TXNetFile::fgRootdBC = kTRUE;
00072 TFileStager *TXNetFile::fgFileStager = 0;
00073
00074
00075 TXNetFile::TXNetFile(const char *url, Option_t *option, const char* ftitle,
00076 Int_t compress, Int_t netopt, Bool_t parallelopen,
00077 const char *logicalurl) :
00078 TNetFile((logicalurl ? logicalurl : url), ftitle, compress, kFALSE)
00079 {
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 TUrl urlnoanchor(url);
00119
00120 EnvPutInt(NAME_DEBUG, gEnv->GetValue("XNet.Debug", -1));
00121
00122
00123 if (!fgInitDone || strstr(urlnoanchor.GetOptions(),"checkenv")) {
00124 SetEnv();
00125 fgInitDone = kTRUE;
00126
00127
00128 if (gEnv->GetValue("XNet.PrintTAG",0) == 1)
00129 Info("TXNetFile","(eXtended TNetFile) %s",
00130 gROOT->GetVersion());
00131 }
00132
00133
00134 urlnoanchor.SetAnchor("");
00135
00136
00137 fInitMtx = new XrdSysRecMutex();
00138
00139 if (gMonitoringWriter) {
00140
00141 if (!fOpenPhases) {
00142 fOpenPhases = new TList;
00143 fOpenPhases->SetOwner();
00144 }
00145
00146 gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "xrdopen", kFALSE);
00147 }
00148
00149
00150 CreateXClient(urlnoanchor.GetUrl(), option, netopt, parallelopen);
00151 }
00152
00153
00154 TXNetFile::~TXNetFile()
00155 {
00156
00157
00158 if (IsOpen())
00159 Close(0);
00160
00161 SafeDelete(fClient);
00162 SafeDelete(fInitMtx);
00163 }
00164
00165
00166 void TXNetFile::FormUrl(TUrl uu, TString &uus)
00167 {
00168
00169
00170
00171 uus = "root://";
00172
00173
00174 if (strlen(uu.GetUser()) > 0) {
00175 uus += uu.GetUser();
00176 uus += "@";
00177 }
00178
00179
00180 if (strlen(uu.GetHost()) > 0) {
00181 uus += uu.GetHost();
00182 }
00183
00184
00185 if (uu.GetPort() > 0) {
00186 uus += ":";
00187 uus += uu.GetPort();
00188 }
00189
00190
00191 uus += "/";
00192 }
00193
00194
00195 Int_t TXNetFile::ParseOptions(const char *opts,
00196 Int_t &cachesz, Int_t &readaheadsz,
00197 Int_t &rmpolicy, Int_t &mxredir, Int_t &rastrategy, Int_t &readtrimblksz)
00198 {
00199
00200 static const char *keys[6] = { "cachesz=", "readaheadsz=", "rmpolicy=",
00201 "mxredir=", "readaheadstrategy=", "readtrimblksz=" };
00202 Int_t fo = 0;
00203 TString s(opts);
00204
00205 UInt_t i = 0;
00206 for (i = 0; i < (sizeof(keys)/sizeof(keys[0])); i++) {
00207 Int_t j = s.Index(keys[i]);
00208 if (j != kNPOS) {
00209 TString val(s(j+strlen(keys[i]), s.Length()));
00210
00211 Int_t k = 0;
00212 while (k < val.Length())
00213 if (!TString(val(k++)).IsDigit())
00214 break;
00215 if (k < val.Length())
00216 val.Remove(--k);
00217 if (val.IsDigit()) {
00218 fo++;
00219 if (i == 0)
00220 cachesz = val.Atoi();
00221 else if (i == 1)
00222 readaheadsz = val.Atoi();
00223 else if (i == 2)
00224 rmpolicy = val.Atoi();
00225 else if (i == 3)
00226 mxredir = val.Atoi();
00227 else if (i == 4)
00228 rastrategy = val.Atoi();
00229 else if (i == 5)
00230 readtrimblksz = val.Atoi();
00231 }
00232 }
00233 }
00234
00235
00236 if (gDebug > 0)
00237 Info("ParseCacheOptions","found: cachesz = %d, readaheadsz = %d, "
00238 "rmpolicy = %d, mxredir = %d, rastrategy = %d, readtrimblksz = %d",
00239 cachesz, readaheadsz, rmpolicy, mxredir, rastrategy, readtrimblksz);
00240
00241
00242 return fo;
00243 }
00244
00245
00246 void TXNetFile::CreateXClient(const char *url, Option_t *option, Int_t netopt,
00247 Bool_t parallelopen)
00248 {
00249
00250
00251 Int_t cachesz = -1, readaheadsz = -1, rmpolicy = -1, mxredir = -1, np = 0;
00252 Int_t readaheadstrategy = -1, readtrimblksz = -1;
00253
00254 fClient = 0;
00255 fNetopt = netopt;
00256
00257
00258 gSystem->Setenv("XRDCLIENTMAXWAIT", Form("%d",TFile::GetOpenTimeout()));
00259
00260 if (GetOnlyStaged()) {
00261
00262 if (!fgFileStager || !(fgFileStager->Matches(url))) {
00263 SafeDelete(fgFileStager);
00264 fgFileStager = TFileStager::Open(url);
00265 }
00266 if (fgFileStager) {
00267 if (!(fgFileStager->IsStaged(url))) {
00268 ::Warning("TXNetFile","<%s> is not staged - StageOnly flag is set!",url);
00269 goto zombie;
00270 }
00271 }
00272 }
00273
00274
00275 fIsRootd = kFALSE;
00276
00277
00278 if (gEnv->GetValue("XNet.ForceParallelOpen", 0))
00279 parallelopen = kTRUE;
00280 fAsyncOpenStatus = (parallelopen) ? kAOSInProgress : fAsyncOpenStatus ;
00281
00282 Bool_t isRootd;
00283 isRootd = kFALSE;
00284
00285
00286 fClient = new XrdClient(url);
00287 if (!fClient) {
00288 fAsyncOpenStatus = (parallelopen) ? kAOSFailure : fAsyncOpenStatus ;
00289 Error("CreateXClient","fatal error: new object creation failed -"
00290 " out of system resources.");
00291 gSystem->Abort();
00292 goto zombie;
00293 }
00294
00295
00296 np = ParseOptions(TUrl(url).GetOptions(),
00297 cachesz, readaheadsz, rmpolicy, mxredir,
00298 readaheadstrategy, readtrimblksz);
00299
00300
00301 if (mxredir > 0) {
00302 if (fClient->GetClientConn()) {
00303 if (gDebug > 0)
00304 Info("CreateXClient", "setting maxredir = %d", mxredir);
00305 fClient->GetClientConn()->SetMaxRedirCnt(mxredir);
00306 }
00307 np--;
00308 }
00309
00310 if (np > 0) {
00311 if (gDebug > 0)
00312 Info("CreateXClient", "setting cachesz = %d, readaheadsz = %d, "
00313 "rmpolicy = %d",
00314 cachesz, readaheadsz, rmpolicy);
00315 fClient->SetCacheParameters(cachesz, readaheadsz, rmpolicy);
00316
00317 if (readaheadstrategy >= 0) {
00318 if (gDebug > 0)
00319 Info("CreateXClient", "setting readaheadstrategy = %d", readaheadstrategy);
00320 fClient->SetReadAheadStrategy(readaheadstrategy);
00321 }
00322
00323 if (readtrimblksz >= 0) {
00324 if (gDebug > 0)
00325 Info("CreateXClient", "setting readtrimblksz = %d", readtrimblksz);
00326 fClient->SetBlockReadTrimming(readtrimblksz);
00327 }
00328
00329 }
00330
00331
00332
00333 if (!Open(option, parallelopen)) {
00334 if (!fClient->IsOpen_wait()) {
00335 if (gDebug > 1)
00336 Info("CreateXClient", "remote file could not be open");
00337
00338
00339 isRootd = (fClient->GetClientConn()->GetServerType() == kSTRootd);
00340
00341 if (isRootd) {
00342 if (fgRootdBC) {
00343
00344 Int_t sd = fClient->GetClientConn()->GetOpenSockFD();
00345 if (sd > -1) {
00346
00347
00348 TSocket *s = new TSocket(sd);
00349
00350 s->SetOption(kNoBlock, 0);
00351
00352
00353 Int_t rproto = GetRootdProtocol(s);
00354 if (rproto < 0) {
00355 Error("CreateXClient", "getting rootd server protocol");
00356 goto zombie;
00357 }
00358
00359
00360 s->SetRemoteProtocol(rproto);
00361 TUrl uut((fClient->GetClientConn()
00362 ->GetCurrentUrl()).GetUrl().c_str());
00363 TString uu;
00364 FormUrl(uut,uu);
00365
00366 if (gDebug > 2)
00367 Info("CreateXClient"," url: %s",uu.Data());
00368 s->SetUrl(uu.Data());
00369 s->SetService("rootd");
00370 s->SetServType(TSocket::kROOTD);
00371
00372
00373 fIsRootd = kTRUE;
00374
00375
00376
00377 if (rproto > 13) {
00378
00379
00380 TNetFile::Create(s, option, netopt);
00381 } else {
00382
00383
00384
00385 TNetFile::Create(uu.Data(), option, netopt);
00386 }
00387
00388 return;
00389 } else {
00390 Error("CreateXClient", "rootd: underlying socket undefined");
00391 goto zombie;
00392 }
00393 } else {
00394 if (gDebug > 0)
00395 Info("CreateXClient", "rootd: fall back not enabled - closing");
00396 goto zombie;
00397 }
00398 } else {
00399 Error("CreateXClient", "open attempt failed on %s", fUrl.GetUrl());
00400 goto zombie;
00401 }
00402 }
00403 }
00404
00405 return;
00406
00407 zombie:
00408
00409 SafeDelete(fClient);
00410 MakeZombie();
00411 gDirectory = gROOT;
00412 }
00413
00414
00415 Int_t TXNetFile::GetRootdProtocol(TSocket *s)
00416 {
00417
00418
00419
00420 Int_t rproto = -1;
00421
00422 UInt_t cproto = 0;
00423 Int_t len = sizeof(cproto);
00424 memcpy((char *)&cproto,
00425 Form(" %d", TSocket::GetClientProtocol()),len);
00426 Int_t ns = s->SendRaw(&cproto, len);
00427 if (ns != len) {
00428 ::Error("TXNetFile::GetRootdProtocol",
00429 "sending %d bytes to rootd server [%s:%d]",
00430 len, (s->GetInetAddress()).GetHostName(), s->GetPort());
00431 return -1;
00432 }
00433
00434
00435 Int_t ibuf[2] = {0};
00436 len = sizeof(ibuf);
00437 Int_t nr = s->RecvRaw(ibuf, len);
00438 if (nr != len) {
00439 ::Error("TXNetFile::GetRootdProtocol",
00440 "reading %d bytes from rootd server [%s:%d]",
00441 len, (s->GetInetAddress()).GetHostName(), s->GetPort());
00442 return -1;
00443 }
00444 Int_t kind = net2host(ibuf[0]);
00445 if (kind == kROOTD_PROTOCOL) {
00446 rproto = net2host(ibuf[1]);
00447 } else {
00448 kind = net2host(ibuf[1]);
00449 if (kind == kROOTD_PROTOCOL) {
00450 len = sizeof(rproto);
00451 nr = s->RecvRaw(&rproto, len);
00452 if (nr != len) {
00453 ::Error("TXNetFile::GetRootdProtocol",
00454 "reading %d bytes from rootd server [%s:%d]",
00455 len, (s->GetInetAddress()).GetHostName(), s->GetPort());
00456 return -1;
00457 }
00458 rproto = net2host(rproto);
00459 }
00460 }
00461 if (gDebug > 2)
00462 ::Info("TXNetFile::GetRootdProtocol",
00463 "remote rootd: buf1: %d, buf2: %d rproto: %d",
00464 net2host(ibuf[0]),net2host(ibuf[1]),rproto);
00465
00466
00467 return rproto;
00468 }
00469
00470
00471 Bool_t TXNetFile::Open(Option_t *option, Bool_t doitparallel)
00472 {
00473
00474
00475
00476
00477 kXR_unt16 openOpt = 0;
00478 memset(&openOpt, 0, sizeof(openOpt));
00479 TString opt = option;
00480 opt.ToUpper();
00481
00482
00483
00484 if (opt.BeginsWith("-") || opt.BeginsWith("F") || (opt == "+READ")) {
00485 opt.Remove(0,1);
00486 openOpt |= kXR_force;
00487 }
00488
00489
00490 Bool_t read = (opt == "READ");
00491
00492
00493 Bool_t create = (opt == "CREATE" || opt == "NEW");
00494
00495
00496 Bool_t recreate = (opt == "RECREATE");
00497
00498
00499 Bool_t update = (opt == "UPDATE");
00500
00501
00502 if (!create && !recreate && !update && !read) {
00503 read = kTRUE;
00504 opt = "READ";
00505 }
00506
00507
00508 fOption = opt;
00509 if (create || update || recreate)
00510 fWritable = 1;
00511
00512
00513
00514 if (update) {
00515 if (gSystem->AccessPathName(fUrl.GetUrl(), kFileExists)) {
00516 update = kFALSE;
00517 create = kTRUE;
00518 }
00519 if (update) {
00520 if (gSystem->AccessPathName(fUrl.GetUrl(), kWritePermission)) {
00521 Error("Open", "no write permission, could not open file %s",
00522 fUrl.GetUrl());
00523 fAsyncOpenStatus = (doitparallel) ? kAOSFailure : fAsyncOpenStatus ;
00524 return kFALSE;
00525 }
00526 openOpt |= kXR_open_updt;
00527 }
00528 }
00529
00530
00531
00532 if (create)
00533 openOpt |= kXR_new;
00534 if (recreate) {
00535 openOpt |= kXR_delete;
00536 create = kTRUE;
00537 }
00538
00539 Bool_t mkpath = (gEnv->GetValue("XNet.Mkpath", 0) == 1) ? kTRUE : kFALSE;
00540 char *p = (char*)strstr(fUrl.GetOptions(), "mkpath=");
00541 if (p)
00542 mkpath = (*(p + strlen("mkpath=")) == '1') ? kTRUE : kFALSE;
00543 if (mkpath)
00544 openOpt |= kXR_mkpath;
00545
00546 if (read)
00547 openOpt |= kXR_open_read;
00548
00549
00550
00551 kXR_unt16 openMode = kXR_or | kXR_gr | kXR_ur | kXR_uw;
00552
00553
00554
00555 if (!fClient->Open(openMode, openOpt, doitparallel)) {
00556 if (gDebug > 1)
00557 Info("Open", "remote file could not be open");
00558 fAsyncOpenStatus = (doitparallel) ? kAOSFailure : fAsyncOpenStatus ;
00559 return kFALSE;
00560 } else {
00561
00562
00563
00564
00565 if (!doitparallel) {
00566
00567 Init(create);
00568
00569 if (TFile::IsZombie()) {
00570 fClient->Close();
00571
00572
00573 fWritable = 0;
00574
00575 return kFALSE;
00576 }
00577 }
00578 }
00579
00580
00581 return kTRUE;
00582 }
00583
00584
00585 Bool_t TXNetFile::ReadBuffer(char *buffer, Int_t bufferLength)
00586 {
00587
00588
00589
00590 if (IsZombie()) {
00591 Error("ReadBuffer", "ReadBuffer is not possible because object"
00592 " is in 'zombie' state");
00593 return kTRUE;
00594 }
00595
00596 if (fIsRootd) {
00597 if (gDebug > 1)
00598 Info("ReadBuffer","Calling TNetFile::ReadBuffer");
00599 return TNetFile::ReadBuffer(buffer, bufferLength);
00600 }
00601
00602 if (!IsOpen()) {
00603 Error("ReadBuffer","The remote file is not open");
00604 return kTRUE;
00605 }
00606
00607 Bool_t result = kFALSE;
00608
00609 if (bufferLength==0)
00610 return 0;
00611
00612
00613
00614
00615
00616
00617 Int_t st = 0;
00618 if (GetCacheRead() && GetCacheRead()->IsAsyncReading()) {
00619 st = ReadBufferViaCache(0, bufferLength);
00620 if (st == 1)
00621 fOffset -= bufferLength;
00622 } else {
00623 if (GetCacheRead()) {
00624 st = ReadBufferViaCache(buffer, bufferLength);
00625 if (st == 1)
00626 return kFALSE;
00627 }
00628 }
00629
00630 Double_t start = 0;
00631 if (gPerfStats) start = TTimeStamp();
00632
00633
00634 Int_t nr = fClient->Read(buffer, fOffset, bufferLength);
00635
00636 if (!nr)
00637 return kTRUE;
00638
00639 if (gDebug > 1)
00640 Info("ReadBuffer", "%d bytes of data read from offset"
00641 " %lld (%d requested)", nr, fOffset, bufferLength);
00642
00643 fOffset += bufferLength;
00644
00645 if (!st) {
00646
00647 fBytesRead += nr;
00648 fReadCalls++;
00649 #ifdef WIN32
00650 SetFileBytesRead(GetFileBytesRead() + nr);
00651 SetFileReadCalls(GetFileReadCalls() + 1);
00652 #else
00653 fgBytesRead += nr;
00654 fgReadCalls++;
00655 #endif
00656
00657 if (gPerfStats)
00658 gPerfStats->FileReadEvent(this, bufferLength, start);
00659
00660 }
00661
00662 if (gMonitoringWriter)
00663 gMonitoringWriter->SendFileReadProgress(this);
00664
00665 return result;
00666 }
00667
00668
00669 Bool_t TXNetFile::ReadBuffer(char *buffer, Long64_t pos, Int_t bufferLength)
00670 {
00671
00672
00673
00674 return TNetFile::ReadBuffer(buffer, pos, bufferLength);
00675 }
00676
00677
00678 Bool_t TXNetFile::ReadBufferAsync(Long64_t offs, Int_t bufferLength)
00679 {
00680
00681
00682
00683
00684
00685 if (IsZombie()) {
00686 Error("ReadBuffer", "ReadBuffer is not possible because object"
00687 " is in 'zombie' state");
00688 return kTRUE;
00689 }
00690
00691 if (fIsRootd) {
00692 if (gDebug > 1)
00693 Error("ReadBufferAsync","Not supported for rootd");
00694 return kTRUE;
00695 }
00696
00697 if (!IsOpen()) {
00698 Error("ReadBuffer","The remote file is not open");
00699 return kTRUE;
00700 }
00701
00702 Double_t start = 0;
00703 if (gPerfStats) start = TTimeStamp();
00704
00705 Bool_t result = kFALSE;
00706
00707 if (bufferLength==0)
00708 return 0;
00709
00710 SynchronizeCacheSize();
00711
00712
00713
00714
00715
00716 XReqErrorType nr = fClient->Read_Async(offs+fArchiveOffset, bufferLength);
00717
00718 if (nr != kOK)
00719 return kTRUE;
00720
00721 fBytesRead += bufferLength;
00722 fReadCalls++;
00723 #ifdef WIN32
00724 SetFileBytesRead(GetFileBytesRead() + bufferLength);
00725 SetFileReadCalls(GetFileReadCalls() + 1);
00726 #else
00727 fgBytesRead += bufferLength;
00728 fgReadCalls++;
00729 #endif
00730
00731 if (gPerfStats)
00732 gPerfStats->FileReadEvent(this, bufferLength, start);
00733
00734 if (gDebug > 1)
00735 Info("ReadBufferAsync", "%d bytes of data read request from offset"
00736 " %lld", bufferLength, offs);
00737 return result;
00738 }
00739
00740
00741 Bool_t TXNetFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
00742 {
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 if (IsZombie()) {
00753 Error("ReadBuffers", "ReadBuffers is not possible because object"
00754 " is in 'zombie' state");
00755 return kTRUE;
00756 }
00757
00758 if (fIsRootd) {
00759 if (gDebug > 1)
00760 Info("ReadBuffers","Calling TNetFile::ReadBuffers");
00761 return TNetFile::ReadBuffers(buf, pos, len, nbuf);
00762 }
00763
00764 if (!IsOpen()) {
00765 Error("ReadBuffers","The remote file is not open");
00766 return kTRUE;
00767 }
00768
00769 Double_t start = 0;
00770 if (gPerfStats) start = TTimeStamp();
00771
00772 if (fArchiveOffset)
00773 for (Int_t i = 0; i < nbuf; i++)
00774 pos[i] += fArchiveOffset;
00775
00776
00777
00778
00779 if (!buf) {
00780
00781 if (!nbuf) ResetCache();
00782 SynchronizeCacheSize();
00783 }
00784
00785
00786 Long64_t nr = fClient->ReadV(buf, pos, len, nbuf);
00787
00788 if (gDebug > 1)
00789 Info("ReadBuffers", "response from ReadV(%d) nr: %lld", nbuf, nr);
00790
00791 if (nr > 0) {
00792
00793 if (gDebug > 1)
00794 Info("ReadBuffers", "%lld bytes of data read from a list of %d buffers",
00795 nr, nbuf);
00796
00797 if (GetCacheRead() && GetCacheRead()->GetBufferSize() < nr)
00798 Info("ReadBuffers", "%lld bytes of data read with a smaller (%d) TFileCacheRead buffer size?",
00799 nr, GetCacheRead()->GetBufferSize());
00800
00801
00802
00803 fBytesRead += nr;
00804 fReadCalls++;
00805 #ifdef WIN32
00806 SetFileBytesRead(GetFileBytesRead() + nr);
00807 SetFileReadCalls(GetFileReadCalls() + 1);
00808 #else
00809 fgBytesRead += nr;
00810 fgReadCalls++;
00811 #endif
00812
00813 if (gPerfStats) {
00814 fOffset = pos[0];
00815 gPerfStats->FileReadEvent(this, pos[nbuf-1]+len[nbuf-1]-pos[0], start);
00816 }
00817
00818 if (gMonitoringWriter)
00819 gMonitoringWriter->SendFileReadProgress(this);
00820
00821 return kFALSE;
00822 }
00823
00824 if (gDebug > 1)
00825 Info("ReadBuffers", "XrdClient->ReadV failed, executing TFile::ReadBuffers");
00826
00827
00828
00829
00830 if (buf && nbuf)
00831 return TFile::ReadBuffers(buf, pos, len, nbuf);
00832
00833
00834 else return kTRUE;
00835 }
00836
00837
00838 Bool_t TXNetFile::WriteBuffer(const char *buffer, Int_t bufferLength)
00839 {
00840
00841
00842
00843 if (IsZombie()) {
00844 Error("WriteBuffer", "WriteBuffer is not possible because object"
00845 " is in 'zombie' state");
00846 return kTRUE;
00847 }
00848
00849 if (!fWritable) {
00850 if (gDebug > 1)
00851 Info("WriteBuffer","file not writable");
00852 return kTRUE;
00853 }
00854
00855 if (fIsRootd) {
00856 if (gDebug > 1)
00857 Info("WriteBuffer","Calling TNetFile::WriteBuffer");
00858 return TNetFile::WriteBuffer(buffer, bufferLength );
00859 }
00860
00861 if (!IsOpen()) {
00862 Error("WriteBuffer","The remote file is not open");
00863 return kTRUE;
00864 }
00865
00866 Int_t st;
00867 if ((st = WriteBufferViaCache(buffer, bufferLength))) {
00868 if (st == 2)
00869 return kTRUE;
00870 return kFALSE;
00871 }
00872
00873
00874 if (!fClient->Write(buffer, fOffset, bufferLength)) {
00875 if (gDebug > 0)
00876 Info("WriteBuffer",
00877 "error writing %d bytes of data wrote to offset %lld",
00878 bufferLength , fOffset);
00879 return kTRUE;
00880 }
00881
00882 if (gDebug > 1)
00883 Info("WriteBuffer", " %d bytes of data wrote to offset"
00884 " %lld", bufferLength , fOffset);
00885
00886 fOffset += bufferLength;
00887 fBytesWrite += bufferLength;
00888 #ifdef WIN32
00889 SetFileBytesWritten(GetFileBytesWritten() + bufferLength);
00890 #else
00891 fgBytesWrite += bufferLength;
00892 #endif
00893
00894 return kFALSE;
00895 }
00896
00897
00898 void TXNetFile::Init(Bool_t create)
00899 {
00900
00901
00902
00903 if (fInitDone) {
00904
00905 if (gDebug > 1)
00906 Info("Init","TFile::Init already called once");
00907 return;
00908 }
00909
00910 if (fIsRootd) {
00911 if (gDebug > 1)
00912 Info("Init","rootd: calling directly TFile::Init");
00913 return TNetFile::Init(create);
00914 }
00915
00916 if (fClient) {
00917
00918 XrdSysMutexHelper m(fInitMtx);
00919
00920
00921
00922 if (fClient->IsOpen_wait()) {
00923
00924
00925 if (gMonitoringWriter)
00926 gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "rootinit", kFALSE);
00927
00928
00929 bool usecachesave = fClient->UseCache(0);
00930
00931 TFile::Init(create);
00932
00933 fD = -2;
00934
00935 fClient->UseCache(usecachesave);
00936
00937
00938 if (gMonitoringWriter)
00939 gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "endopen", kTRUE);
00940
00941
00942
00943 if (fClient->GetClientConn() && fClient->GetClientConn()->fRedirOpaque.length() <= 0) {
00944 fEndpointUrl = fClient->GetClientConn()->GetCurrentUrl().GetUrl().c_str();
00945
00946
00947 if (fEndpointUrl.GetPort() != fUrl.GetPort() ||
00948 strcmp(fEndpointUrl.GetHostFQDN(), fUrl.GetHostFQDN()))
00949 SetBit(TFile::kRedirected);
00950 }
00951 } else {
00952 if (gDebug > 0)
00953 Info("Init","open request failed!");
00954 SafeDelete(fClient);
00955 MakeZombie();
00956 gDirectory = gROOT;
00957 }
00958 }
00959 }
00960
00961
00962 Bool_t TXNetFile::IsOpen() const
00963 {
00964
00965
00966 if (fIsRootd) {
00967 if (gDebug > 1)
00968 Info("IsOpen","Calling TNetFile::IsOpen");
00969 return TNetFile::IsOpen();
00970 }
00971
00972 if (!fClient)
00973 return kFALSE;
00974
00975
00976 return ((fClient && fInitDone) ? fClient->IsOpen() : kFALSE);
00977 }
00978
00979
00980 TFile::EAsyncOpenStatus TXNetFile::GetAsyncOpenStatus()
00981 {
00982
00983
00984 if (fAsyncOpenStatus != TFile::kAOSNotAsync) {
00985 if (fClient->IsOpen_inprogress()) {
00986 return TFile::kAOSInProgress;
00987 } else {
00988 if (fClient->IsOpen())
00989 return TFile::kAOSSuccess;
00990 else
00991 return TFile::kAOSFailure;
00992 }
00993 }
00994
00995
00996 return TFile::kAOSNotAsync;
00997 }
00998
00999
01000 Int_t TXNetFile::ReOpen(const Option_t *Mode)
01001 {
01002
01003
01004
01005 if (fIsRootd) {
01006 if (gDebug > 1)
01007 Info("ReOpen","Calling TNetFile::ReOpen");
01008 return TNetFile::ReOpen(Mode);
01009 }
01010
01011 return TFile::ReOpen(Mode);
01012 }
01013
01014
01015 void TXNetFile::Close(const Option_t *opt)
01016 {
01017
01018
01019
01020 if (fIsRootd) {
01021 if (gDebug > 1)
01022 Info("Close","Calling TNetFile::Close");
01023 TNetFile::Close(opt);
01024 return;
01025 }
01026
01027 if (!fClient) return;
01028
01029 TFile::Close(opt);
01030
01031 fIsRootd = kFALSE;
01032
01033 if (IsOpen())
01034 fClient->Close();
01035
01036 fD = -1;
01037 }
01038
01039
01040 void TXNetFile::Flush()
01041 {
01042
01043 if (IsZombie()) {
01044 Error("Flush", "Flush is not possible because object is"
01045 " in 'zombie' state");
01046 return;
01047 }
01048
01049 if (!fWritable) {
01050 if (gDebug > 1)
01051 Info("Flush", "file not writable - do nothing");
01052 return;
01053 }
01054
01055 if (fIsRootd) {
01056 if (gDebug > 1)
01057 Info("Flush","Calling TNetFile::Flush");
01058 TNetFile::Flush();
01059 return;
01060 }
01061
01062 if (!IsOpen()) {
01063 Error("Flush","The remote file is not open");
01064 return;
01065 }
01066
01067 FlushWriteCache();
01068
01069
01070
01071 fClient->Sync();
01072 if (gDebug > 1)
01073 Info("Flush", "XrdClient::Sync called.");
01074 }
01075
01076
01077 Int_t TXNetFile::SysStat(Int_t fd, Long_t *id, Long64_t *size, Long_t *flags,
01078 Long_t *modtime)
01079 {
01080
01081
01082 if (IsZombie()) {
01083 Error("SysStat", "SysStat is not possible because object is"
01084 " in 'zombie' state");
01085 *size = 0;
01086 return 1;
01087 }
01088
01089 if (fIsRootd) {
01090 if (gDebug > 1)
01091 Info("SysStat", "calling TNetFile::SysStat");
01092 return TNetFile::SysStat(fd, id, size, flags, modtime);
01093 }
01094
01095
01096
01097 struct XrdClientStatInfo stinfo;
01098 if (fClient && fClient->Stat(&stinfo)) {
01099 *id = (Long_t)(stinfo.id);
01100 *size = (Long64_t)(stinfo.size);
01101 *flags = (Long_t)(stinfo.flags);
01102 *modtime = (Long_t)(stinfo.modtime);
01103 if (gDebug > 1)
01104 Info("SysStat", "got stats = %ld %lld %ld %ld",
01105 *id, *size, *flags, *modtime);
01106 } else {
01107
01108 if (gDebug > 1) {
01109 if (!IsOpen()) Info("SysStat", "could not stat remote file. Not opened.");
01110 else
01111 Info("SysStat", "could not stat remote file");
01112 }
01113
01114
01115 *id = -1;
01116 return 1;
01117 }
01118
01119
01120 return 0;
01121 }
01122
01123
01124 Int_t TXNetFile::SysClose(Int_t fd)
01125 {
01126
01127
01128 if (IsZombie()) {
01129 Error("SysClose", "SysClose is not possible because object is"
01130 " in 'zombie' state");
01131 return 0;
01132 }
01133
01134 if (fIsRootd) {
01135 if (gDebug > 1)
01136 Info("SysClose","Calling TNetFile::SysClose");
01137 return TNetFile::SysClose(fd);
01138 }
01139
01140
01141 if (IsOpen())
01142 fClient->Close();
01143
01144 return 0;
01145 }
01146
01147
01148 Int_t TXNetFile::SysOpen(const char* pathname, Int_t flags, UInt_t mode)
01149 {
01150
01151
01152 if (fIsRootd) {
01153 if (gDebug > 1)
01154 Info("SysOpen", "Calling TNetFile::SysOpen");
01155 return TNetFile::SysOpen(pathname, flags, mode);
01156 }
01157
01158 if (!fClient) {
01159
01160
01161 CreateXClient(fUrl.GetUrl(), fOption, fNetopt, kFALSE);
01162
01163 } else {
01164
01165
01166
01167 Open(fOption.Data(), kFALSE);
01168 }
01169
01170
01171 if (!IsOpen())
01172 return -1;
01173
01174
01175 return -2;
01176 }
01177
01178
01179 void TXNetFile::SetEnv()
01180 {
01181
01182
01183
01184 TString allowRE = gEnv->GetValue("XNet.RedirDomainAllowRE", "");
01185 if (allowRE.Length() > 0)
01186 EnvPutString(NAME_REDIRDOMAINALLOW_RE, allowRE.Data());
01187
01188
01189 TString denyRE = gEnv->GetValue("XNet.RedirDomainDenyRE", "");
01190 if (denyRE.Length() > 0)
01191 EnvPutString(NAME_REDIRDOMAINDENY_RE, denyRE.Data());
01192
01193
01194 TString allowCO = gEnv->GetValue("XNet.ConnectDomainAllowRE", "");
01195 if (allowCO.Length() > 0)
01196 EnvPutString(NAME_CONNECTDOMAINALLOW_RE, allowCO.Data());
01197
01198
01199 TString denyCO = gEnv->GetValue("XNet.ConnectDomainDenyRE", "");
01200 if (denyCO.Length() > 0)
01201 EnvPutString(NAME_CONNECTDOMAINDENY_RE, denyCO.Data());
01202
01203
01204 Int_t connTO = gEnv->GetValue("XNet.ConnectTimeout",
01205 DFLT_CONNECTTIMEOUT);
01206 EnvPutInt(NAME_CONNECTTIMEOUT, connTO);
01207
01208
01209 Int_t recoTO = gEnv->GetValue("XNet.ReconnectWait",
01210 DFLT_RECONNECTWAIT);
01211 if (recoTO == DFLT_RECONNECTWAIT) {
01212
01213 recoTO = gEnv->GetValue("XNet.ReconnectTimeout",
01214 DFLT_RECONNECTWAIT);
01215 }
01216 EnvPutInt(NAME_RECONNECTWAIT, recoTO);
01217
01218
01219 Int_t requTO = gEnv->GetValue("XNet.RequestTimeout",
01220 DFLT_REQUESTTIMEOUT);
01221 EnvPutInt(NAME_REQUESTTIMEOUT, requTO);
01222
01223
01224 Int_t maxRedir = gEnv->GetValue("XNet.MaxRedirectCount",
01225 DFLT_MAXREDIRECTCOUNT);
01226 EnvPutInt(NAME_MAXREDIRECTCOUNT, maxRedir);
01227
01228
01229
01230 Int_t rAheadsiz = gEnv->GetValue("XNet.ReadAheadSize",
01231 DFLT_READAHEADSIZE);
01232 EnvPutInt(NAME_READAHEADSIZE, rAheadsiz);
01233
01234
01235
01236 Int_t rCachesiz = gEnv->GetValue("XNet.ReadCacheSize",
01237 DFLT_READCACHESIZE);
01238
01239 EnvPutInt(NAME_READCACHESIZE, rCachesiz);
01240
01241
01242 Int_t maxRetries = gEnv->GetValue("XNet.FirstConnectMaxCnt",
01243 DFLT_FIRSTCONNECTMAXCNT);
01244 EnvPutInt(NAME_FIRSTCONNECTMAXCNT, maxRetries);
01245
01246
01247 Int_t parStreamsCnt = gEnv->GetValue("XNet.ParStreamsPerPhyConn",
01248 DFLT_MULTISTREAMCNT);
01249 EnvPutInt(NAME_MULTISTREAMCNT, parStreamsCnt);
01250
01251
01252 Int_t tcpWindowSize = gEnv->GetValue("XNet.DfltTcpWindowSize",
01253 DFLT_DFLTTCPWINDOWSIZE);
01254 EnvPutInt(NAME_DFLTTCPWINDOWSIZE, tcpWindowSize);
01255
01256
01257 Int_t transactionTimeout = gEnv->GetValue("XNet.TransactionTimeout",
01258 DFLT_TRANSACTIONTIMEOUT);
01259 EnvPutInt(NAME_TRANSACTIONTIMEOUT, transactionTimeout);
01260
01261
01262
01263 fgRootdBC = gEnv->GetValue("XNet.RootdFallback", 1);
01264 EnvPutInt(NAME_KEEPSOCKOPENIFNOTXRD, fgRootdBC);
01265
01266
01267 TString socks4Host = gEnv->GetValue("XNet.SOCKS4Host","");
01268 Int_t socks4Port = gEnv->GetValue("XNet.SOCKS4Port",-1);
01269 if (socks4Port > 0) {
01270 if (socks4Host.IsNull())
01271
01272 socks4Host = "127.0.0.1";
01273 EnvPutString(NAME_SOCKS4HOST, socks4Host.Data());
01274 EnvPutInt(NAME_SOCKS4PORT, socks4Port);
01275 }
01276
01277 const char *cenv = 0;
01278
01279
01280 TString autolog = gEnv->GetValue("XSec.Pwd.AutoLogin","1");
01281 if (autolog.Length() > 0 &&
01282 (!(cenv = gSystem->Getenv("XrdSecPWDAUTOLOG")) || strlen(cenv) <= 0))
01283 gSystem->Setenv("XrdSecPWDAUTOLOG",autolog.Data());
01284
01285
01286 TString netrc;
01287 netrc.Form("%s/.rootnetrc",gSystem->HomeDirectory());
01288 gSystem->Setenv("XrdSecNETRC", netrc.Data());
01289
01290 TString alogfile = gEnv->GetValue("XSec.Pwd.ALogFile","");
01291 if (alogfile.Length() > 0)
01292 gSystem->Setenv("XrdSecPWDALOGFILE",alogfile.Data());
01293
01294 TString verisrv = gEnv->GetValue("XSec.Pwd.VerifySrv","1");
01295 if (verisrv.Length() > 0 &&
01296 (!(cenv = gSystem->Getenv("XrdSecPWDVERIFYSRV")) || strlen(cenv) <= 0))
01297 gSystem->Setenv("XrdSecPWDVERIFYSRV",verisrv.Data());
01298
01299 TString srvpuk = gEnv->GetValue("XSec.Pwd.ServerPuk","");
01300 if (srvpuk.Length() > 0)
01301 gSystem->Setenv("XrdSecPWDSRVPUK",srvpuk.Data());
01302
01303
01304 TString cadir = gEnv->GetValue("XSec.GSI.CAdir","");
01305 if (cadir.Length() > 0)
01306 gSystem->Setenv("XrdSecGSICADIR",cadir.Data());
01307
01308 TString crldir = gEnv->GetValue("XSec.GSI.CRLdir","");
01309 if (crldir.Length() > 0)
01310 gSystem->Setenv("XrdSecGSICRLDIR",crldir.Data());
01311
01312 TString crlext = gEnv->GetValue("XSec.GSI.CRLextension","");
01313 if (crlext.Length() > 0)
01314 gSystem->Setenv("XrdSecGSICRLEXT",crlext.Data());
01315
01316 TString ucert = gEnv->GetValue("XSec.GSI.UserCert","");
01317 if (ucert.Length() > 0)
01318 gSystem->Setenv("XrdSecGSIUSERCERT",ucert.Data());
01319
01320 TString ukey = gEnv->GetValue("XSec.GSI.UserKey","");
01321 if (ukey.Length() > 0)
01322 gSystem->Setenv("XrdSecGSIUSERKEY",ukey.Data());
01323
01324 TString upxy = gEnv->GetValue("XSec.GSI.UserProxy","");
01325 if (upxy.Length() > 0)
01326 gSystem->Setenv("XrdSecGSIUSERPROXY",upxy.Data());
01327
01328 TString valid = gEnv->GetValue("XSec.GSI.ProxyValid","");
01329 if (valid.Length() > 0)
01330 gSystem->Setenv("XrdSecGSIPROXYVALID",valid.Data());
01331
01332 TString deplen = gEnv->GetValue("XSec.GSI.ProxyForward","0");
01333 if (deplen.Length() > 0 &&
01334 (!(cenv = gSystem->Getenv("XrdSecGSIPROXYDEPLEN")) || strlen(cenv) <= 0))
01335 gSystem->Setenv("XrdSecGSIPROXYDEPLEN",deplen.Data());
01336
01337 TString pxybits = gEnv->GetValue("XSec.GSI.ProxyKeyBits","");
01338 if (pxybits.Length() > 0)
01339 gSystem->Setenv("XrdSecGSIPROXYKEYBITS",pxybits.Data());
01340
01341 TString crlcheck = gEnv->GetValue("XSec.GSI.CheckCRL","1");
01342 if (crlcheck.Length() > 0 &&
01343 (!(cenv = gSystem->Getenv("XrdSecGSICRLCHECK")) || strlen(cenv) <= 0))
01344 gSystem->Setenv("XrdSecGSICRLCHECK",crlcheck.Data());
01345
01346 TString delegpxy = gEnv->GetValue("XSec.GSI.DelegProxy","0");
01347 if (delegpxy.Length() > 0 &&
01348 (!(cenv = gSystem->Getenv("XrdSecGSIDELEGPROXY")) || strlen(cenv) <= 0))
01349 gSystem->Setenv("XrdSecGSIDELEGPROXY",delegpxy.Data());
01350
01351 TString signpxy = gEnv->GetValue("XSec.GSI.SignProxy","1");
01352 if (signpxy.Length() > 0 &&
01353 (!(cenv = gSystem->Getenv("XrdSecGSISIGNPROXY")) || strlen(cenv) <= 0))
01354 gSystem->Setenv("XrdSecGSISIGNPROXY",signpxy.Data());
01355
01356
01357 gSystem->IgnoreSignal(kSigPipe);
01358 }
01359
01360
01361 void TXNetFile::SynchronizeCacheSize()
01362 {
01363
01364
01365
01366 if (fClient == 0) return;
01367
01368 fClient->UseCache(TRUE);
01369 Int_t size;
01370 Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
01371 Float_t missrate, bytesusefulness;
01372 int newbsz = -1;
01373 if (fClient->GetCacheInfo(size, bytessubmitted,
01374 byteshit, misscount,
01375 missrate, readreqcnt,
01376 bytesusefulness) ) {
01377
01378
01379 TFileCacheRead *cacheRead = GetCacheRead();
01380 if (cacheRead) {
01381 newbsz = GetBufferSize() / 2 * 3;
01382 newbsz = TMath::Max(newbsz, size);
01383 } else {
01384 newbsz = size;
01385 }
01386
01387 }
01388
01389 if (newbsz > 0)
01390 fClient->SetCacheParameters(newbsz, 0, XrdClientReadCache::kRmBlk_FIFO);
01391 }
01392
01393
01394 void TXNetFile::ResetCache()
01395 {
01396
01397
01398 if (fClient)
01399 fClient->RemoveAllDataFromCache();
01400 }
01401
01402
01403 Int_t TXNetFile::GetBytesToPrefetch() const
01404 {
01405
01406
01407 Int_t size;
01408 Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
01409 Float_t missrate, bytesusefulness;
01410 Int_t bytes = 0;
01411 if (fClient && fClient->GetCacheInfo(size, bytessubmitted,
01412 byteshit, misscount,
01413 missrate, readreqcnt,
01414 bytesusefulness) )
01415 bytes = size;
01416 return ((bytes < 0) ? 0 : bytes);
01417 }
01418
01419
01420 void TXNetFile::Print(Option_t *option) const
01421 {
01422
01423
01424 Printf("TXNetFile caching information:");
01425
01426 Int_t size;
01427 Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
01428 Float_t missrate, bytesusefulness;
01429
01430 if (fClient && fClient->GetCacheInfo(size, bytessubmitted,
01431 byteshit, misscount,
01432 missrate, readreqcnt,
01433 bytesusefulness)) {
01434 Printf(" Max size: %d", size);
01435 Printf(" Bytes submitted: %lld", bytessubmitted);
01436 Printf(" Bytes hit (estimation): %lld", byteshit);
01437 Printf(" Miss count: %lld", misscount);
01438 Printf(" Miss rate: %f", missrate);
01439 Printf(" Read requests count: %lld", readreqcnt);
01440 Printf(" Bytes usefulness: %f\n", bytesusefulness);
01441 } else
01442 Printf(" -- No Xrd client instance allocated --\n");
01443
01444 TFile::Print(option);
01445 }