#include "Bytes.h"
#include "TError.h"
#include "TEnv.h"
#include "TSocket.h"
#include "TXNetFile.h"
#include "TROOT.h"
#include "TVirtualMonitoring.h"
#include "TFileStager.h"
#include "TFileCacheRead.h"
#include "TTimeStamp.h"
#include "TVirtualPerfStats.h"
#include <XrdClient/XrdClient.hh>
#include <XrdClient/XrdClientConn.hh>
#include <XrdClient/XrdClientConst.hh>
#include <XrdClient/XrdClientEnv.hh>
#include <XProtocol/XProtocol.hh>
#include "XpdSysPthread.h"
#include "XrdSysToOuc.h"
ClassImp(TXNetFile);
Bool_t TXNetFile::fgInitDone = kFALSE;
Bool_t TXNetFile::fgRootdBC = kTRUE;
TFileStager *TXNetFile::fgFileStager = 0;
TXNetFile::TXNetFile(const char *url, Option_t *option, const char* ftitle,
Int_t compress, Int_t netopt, Bool_t parallelopen,
const char *logicalurl) :
TNetFile((logicalurl ? logicalurl : url), ftitle, compress, kFALSE)
{
TUrl urlnoanchor(url);
EnvPutInt(NAME_DEBUG, gEnv->GetValue("XNet.Debug", 0));
if (!fgInitDone || strstr(urlnoanchor.GetOptions(),"checkenv")) {
SetEnv();
fgInitDone = kTRUE;
if (gEnv->GetValue("XNet.PrintTAG",0) == 1)
Info("TXNetFile","(eXtended TNetFile) %s",
gROOT->GetVersion());
}
urlnoanchor.SetAnchor("");
fInitMtx = (void *) new XrdSysRecMutex();
if (gMonitoringWriter) {
if (!fOpenPhases) {
fOpenPhases = new TList;
fOpenPhases->SetOwner();
}
gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "xrdopen", kFALSE);
}
CreateXClient(urlnoanchor.GetUrl(), option, netopt, parallelopen);
}
TXNetFile::~TXNetFile()
{
if (IsOpen())
Close(0);
SafeDelete(fClient);
XrdSysRecMutex *mtx = (XrdSysRecMutex *)fInitMtx;
if (mtx) delete mtx;
fInitMtx = 0;
}
void TXNetFile::FormUrl(TUrl uu, TString &uus)
{
uus = "root://";
if (strlen(uu.GetUser()) > 0) {
uus += uu.GetUser();
uus += "@";
}
if (strlen(uu.GetHost()) > 0) {
uus += uu.GetHost();
}
if (uu.GetPort() > 0) {
uus += ":";
uus += uu.GetPort();
}
uus += "/";
}
Int_t TXNetFile::ParseOptions(const char *opts,
Int_t &cachesz, Int_t &readaheadsz,
Int_t &rmpolicy, Int_t &mxredir, Int_t &rastrategy, Int_t &readtrimblksz)
{
static const char *keys[6] = { "cachesz=", "readaheadsz=", "rmpolicy=",
"mxredir=", "readaheadstrategy=", "readtrimblksz=" };
Int_t fo = 0;
TString s(opts);
UInt_t i = 0;
for (i = 0; i < (sizeof(keys)/sizeof(keys[0])); i++) {
Int_t j = s.Index(keys[i]);
if (j != kNPOS) {
TString val(s(j+strlen(keys[i]), s.Length()));
Int_t k = 0;
while (k < val.Length())
if (!TString(val(k++)).IsDigit())
break;
if (k < val.Length())
val.Remove(--k);
if (val.IsDigit()) {
fo++;
if (i == 0)
cachesz = val.Atoi();
else if (i == 1)
readaheadsz = val.Atoi();
else if (i == 2)
rmpolicy = val.Atoi();
else if (i == 3)
mxredir = val.Atoi();
else if (i == 4)
rastrategy = val.Atoi();
else if (i == 5)
readtrimblksz = val.Atoi();
}
}
}
if (gDebug > 0)
Info("ParseCacheOptions","found: cachesz = %d, readaheadsz = %d, "
"rmpolicy = %d, mxredir = %d, rastrategy = %d, readtrimblksz = %d",
cachesz, readaheadsz, rmpolicy, mxredir, rastrategy, readtrimblksz);
return fo;
}
void TXNetFile::CreateXClient(const char *url, Option_t *option, Int_t netopt,
Bool_t parallelopen)
{
Int_t cachesz = -1, readaheadsz = -1, rmpolicy = -1, mxredir = -1, np = 0;
Int_t readaheadstrategy = -1, readtrimblksz = -1;
fClient = 0;
fNetopt = netopt;
gSystem->Setenv("XRDCLIENTMAXWAIT", Form("%d",TFile::GetOpenTimeout()));
if (GetOnlyStaged()) {
if (!fgFileStager || !(fgFileStager->Matches(url))) {
SafeDelete(fgFileStager);
fgFileStager = TFileStager::Open(url);
}
if (fgFileStager) {
if (!(fgFileStager->IsStaged(url))) {
::Warning("TXNetFile","<%s> is not staged - StageOnly flag is set!",url);
goto zombie;
}
}
}
fIsRootd = kFALSE;
if (gEnv->GetValue("XNet.ForceParallelOpen", 0))
parallelopen = kTRUE;
fAsyncOpenStatus = (parallelopen) ? kAOSInProgress : fAsyncOpenStatus ;
Bool_t isRootd;
isRootd = kFALSE;
fClient = new XrdClient(url);
if (!fClient) {
fAsyncOpenStatus = (parallelopen) ? kAOSFailure : fAsyncOpenStatus ;
Error("CreateXClient","fatal error: new object creation failed -"
" out of system resources.");
gSystem->Abort();
goto zombie;
}
np = ParseOptions(TUrl(url).GetOptions(),
cachesz, readaheadsz, rmpolicy, mxredir,
readaheadstrategy, readtrimblksz);
if (mxredir > 0) {
if (fClient->GetClientConn()) {
if (gDebug > 0)
Info("CreateXClient", "setting maxredir = %d", mxredir);
fClient->GetClientConn()->SetMaxRedirCnt(mxredir);
}
np--;
}
if (np > 0) {
if (gDebug > 0)
Info("CreateXClient", "setting cachesz = %d, readaheadsz = %d, "
"rmpolicy = %d",
cachesz, readaheadsz, rmpolicy);
fClient->SetCacheParameters(cachesz, readaheadsz, rmpolicy);
if (readaheadstrategy >= 0) {
if (gDebug > 0)
Info("CreateXClient", "setting readaheadstrategy = %d", readaheadstrategy);
fClient->SetReadAheadStrategy(readaheadstrategy);
}
if (readtrimblksz >= 0) {
if (gDebug > 0)
Info("CreateXClient", "setting readtrimblksz = %d", readtrimblksz);
fClient->SetBlockReadTrimming(readtrimblksz);
}
}
if (!Open(option, parallelopen)) {
if (!fClient->IsOpen_wait()) {
if (gDebug > 1)
Info("CreateXClient", "remote file could not be open");
isRootd = (fClient->GetClientConn()->GetServerType() == kSTRootd);
if (isRootd) {
if (fgRootdBC) {
Int_t sd = fClient->GetClientConn()->GetOpenSockFD();
if (sd > -1) {
TSocket *s = new TSocket(sd);
s->SetOption(kNoBlock, 0);
Int_t rproto = GetRootdProtocol(s);
if (rproto < 0) {
Error("CreateXClient", "getting rootd server protocol");
goto zombie;
}
s->SetRemoteProtocol(rproto);
TUrl uut((fClient->GetClientConn()
->GetCurrentUrl()).GetUrl().c_str());
TString uu;
FormUrl(uut,uu);
if (gDebug > 2)
Info("CreateXClient"," url: %s",uu.Data());
s->SetUrl(uu.Data());
s->SetService("rootd");
s->SetServType(TSocket::kROOTD);
fIsRootd = kTRUE;
if (rproto > 13) {
TNetFile::Create(s, option, netopt);
} else {
TNetFile::Create(uu.Data(), option, netopt);
}
return;
} else {
Error("CreateXClient", "rootd: underlying socket undefined");
goto zombie;
}
} else {
if (gDebug > 0)
Info("CreateXClient", "rootd: fall back not enabled - closing");
goto zombie;
}
} else {
Error("CreateXClient", "open attempt failed on %s", fUrl.GetUrl());
goto zombie;
}
}
}
return;
zombie:
SafeDelete(fClient);
MakeZombie();
gDirectory = gROOT;
}
Int_t TXNetFile::GetRootdProtocol(TSocket *s)
{
Int_t rproto = -1;
UInt_t cproto = 0;
Int_t len = sizeof(cproto);
memcpy((char *)&cproto,
Form(" %d", TSocket::GetClientProtocol()),len);
Int_t ns = s->SendRaw(&cproto, len);
if (ns != len) {
::Error("TXNetFile::GetRootdProtocol",
"sending %d bytes to rootd server [%s:%d]",
len, (s->GetInetAddress()).GetHostName(), s->GetPort());
return -1;
}
Int_t ibuf[2] = {0};
len = sizeof(ibuf);
Int_t nr = s->RecvRaw(ibuf, len);
if (nr != len) {
::Error("TXNetFile::GetRootdProtocol",
"reading %d bytes from rootd server [%s:%d]",
len, (s->GetInetAddress()).GetHostName(), s->GetPort());
return -1;
}
Int_t kind = net2host(ibuf[0]);
if (kind == kROOTD_PROTOCOL) {
rproto = net2host(ibuf[1]);
} else {
kind = net2host(ibuf[1]);
if (kind == kROOTD_PROTOCOL) {
len = sizeof(rproto);
nr = s->RecvRaw(&rproto, len);
if (nr != len) {
::Error("TXNetFile::GetRootdProtocol",
"reading %d bytes from rootd server [%s:%d]",
len, (s->GetInetAddress()).GetHostName(), s->GetPort());
return -1;
}
rproto = net2host(rproto);
}
}
if (gDebug > 2)
::Info("TXNetFile::GetRootdProtocol",
"remote rootd: buf1: %d, buf2: %d rproto: %d",
net2host(ibuf[0]),net2host(ibuf[1]),rproto);
return rproto;
}
Bool_t TXNetFile::Open(Option_t *option, Bool_t doitparallel)
{
kXR_unt16 openOpt = 0;
memset(&openOpt, 0, sizeof(openOpt));
TString opt = option;
opt.ToUpper();
if (opt.BeginsWith("-") || opt.BeginsWith("F") || (opt == "+READ")) {
opt.Remove(0,1);
openOpt |= kXR_force;
}
Bool_t read = (opt == "READ");
Bool_t create = (opt == "CREATE" || opt == "NEW");
Bool_t recreate = (opt == "RECREATE");
Bool_t update = (opt == "UPDATE");
if (!create && !recreate && !update && !read) {
read = kTRUE;
opt = "READ";
}
fOption = opt;
if (create || update || recreate)
fWritable = 1;
if (update) {
if (gSystem->AccessPathName(fUrl.GetUrl(), kFileExists)) {
update = kFALSE;
create = kTRUE;
}
if (update) {
if (gSystem->AccessPathName(fUrl.GetUrl(), kWritePermission)) {
Error("Open", "no write permission, could not open file %s",
fUrl.GetUrl());
fAsyncOpenStatus = (doitparallel) ? kAOSFailure : fAsyncOpenStatus ;
return kFALSE;
}
openOpt |= kXR_open_updt;
}
}
if (create)
openOpt |= kXR_new;
if (recreate) {
openOpt |= kXR_delete;
create = kTRUE;
}
Bool_t mkpath = (gEnv->GetValue("XNet.Mkpath", 0) == 1) ? kTRUE : kFALSE;
char *p = (char*)strstr(fUrl.GetOptions(), "mkpath=");
if (p)
mkpath = (*(p + strlen("mkpath=")) == '1') ? kTRUE : kFALSE;
if (mkpath)
openOpt |= kXR_mkpath;
if (read)
openOpt |= kXR_open_read;
kXR_unt16 openMode = kXR_or | kXR_gr | kXR_ur | kXR_uw;
if (!fClient->Open(openMode, openOpt, doitparallel)) {
if (gDebug > 1)
Info("Open", "remote file could not be open");
fAsyncOpenStatus = (doitparallel) ? kAOSFailure : fAsyncOpenStatus ;
return kFALSE;
} else {
if (!doitparallel) {
Init(create);
if (TFile::IsZombie()) {
fClient->Close();
fWritable = 0;
return kFALSE;
}
}
}
return kTRUE;
}
Bool_t TXNetFile::ReadBuffer(char *buffer, Int_t bufferLength)
{
if (IsZombie()) {
Error("ReadBuffer", "ReadBuffer is not possible because object"
" is in 'zombie' state");
return kTRUE;
}
if (fIsRootd) {
if (gDebug > 1)
Info("ReadBuffer","Calling TNetFile::ReadBuffer");
return TNetFile::ReadBuffer(buffer, bufferLength);
}
if (!IsOpen()) {
Error("ReadBuffer","The remote file is not open");
return kTRUE;
}
Bool_t result = kFALSE;
if (bufferLength==0)
return 0;
Int_t st = 0;
if (GetCacheRead() && GetCacheRead()->IsEnablePrefetching()) {
st = ReadBufferViaCache(buffer, bufferLength);
if (st == 1){
fOffset -= bufferLength;
return kFALSE;
}
}
else{
if (GetCacheRead() && GetCacheRead()->IsAsyncReading()) {
st = ReadBufferViaCache(0, bufferLength);
if (st == 1)
fOffset -= bufferLength;
} else {
if (GetCacheRead()) {
st = ReadBufferViaCache(buffer, bufferLength);
if (st == 1)
return kFALSE;
}
}
}
Double_t start = 0;
if (gPerfStats) start = TTimeStamp();
Int_t nr = fClient->Read(buffer, fOffset, bufferLength);
if (!nr)
return kTRUE;
if (gDebug > 1)
Info("ReadBuffer", "%d bytes of data read from offset"
" %lld (%d requested)", nr, fOffset, bufferLength);
fOffset += bufferLength;
fBytesRead += nr;
fReadCalls++;
#ifdef WIN32
SetFileBytesRead(GetFileBytesRead() + nr);
SetFileReadCalls(GetFileReadCalls() + 1);
#else
fgBytesRead += nr;
fgReadCalls++;
#endif
if (gPerfStats)
gPerfStats->FileReadEvent(this, bufferLength, start);
if (gMonitoringWriter)
gMonitoringWriter->SendFileReadProgress(this);
return result;
}
Bool_t TXNetFile::ReadBuffer(char *buffer, Long64_t pos, Int_t bufferLength)
{
return TNetFile::ReadBuffer(buffer, pos, bufferLength);
}
Bool_t TXNetFile::ReadBufferAsync(Long64_t offs, Int_t bufferLength)
{
if (IsZombie()) {
Error("ReadBuffer", "ReadBuffer is not possible because object"
" is in 'zombie' state");
return kTRUE;
}
if (fIsRootd) {
if (gDebug > 1)
Error("ReadBufferAsync","Not supported for rootd");
return kTRUE;
}
if (!IsOpen()) {
Error("ReadBuffer","The remote file is not open");
return kTRUE;
}
Double_t start = 0;
if (gPerfStats) start = TTimeStamp();
Bool_t result = kFALSE;
if (bufferLength==0)
return 0;
SynchronizeCacheSize();
XReqErrorType nr = fClient->Read_Async(offs+fArchiveOffset, bufferLength);
if (nr != kOK)
return kTRUE;
fBytesRead += bufferLength;
fReadCalls++;
#ifdef WIN32
SetFileBytesRead(GetFileBytesRead() + bufferLength);
SetFileReadCalls(GetFileReadCalls() + 1);
#else
fgBytesRead += bufferLength;
fgReadCalls++;
#endif
if (gPerfStats)
gPerfStats->FileReadEvent(this, bufferLength, start);
if (gDebug > 1)
Info("ReadBufferAsync", "%d bytes of data read request from offset"
" %lld", bufferLength, offs);
return result;
}
Bool_t TXNetFile::ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
{
if (IsZombie()) {
Error("ReadBuffers", "ReadBuffers is not possible because object"
" is in 'zombie' state");
return kTRUE;
}
if (fIsRootd) {
if (gDebug > 1)
Info("ReadBuffers","Calling TNetFile::ReadBuffers");
return TNetFile::ReadBuffers(buf, pos, len, nbuf);
}
if (!IsOpen()) {
Error("ReadBuffers","The remote file is not open");
return kTRUE;
}
Double_t start = 0;
if (gPerfStats) start = TTimeStamp();
if (fArchiveOffset) {
for (Int_t i = 0; i < nbuf; i++)
pos[i] += fArchiveOffset;
}
if (!buf) {
if (!nbuf) ResetCache();
SynchronizeCacheSize();
}
Long64_t nr = fClient->ReadV(buf, pos, len, nbuf);
if (gDebug > 1)
Info("ReadBuffers", "response from ReadV(%d) nr: %lld", nbuf, nr);
if (nr > 0) {
if (gDebug > 1)
Info("ReadBuffers", "%lld bytes of data read from a list of %d buffers",
nr, nbuf);
if (GetCacheRead() && GetCacheRead()->GetBufferSize() < nr)
Info("ReadBuffers", "%lld bytes of data read with a smaller (%d) TFileCacheRead buffer size?",
nr, GetCacheRead()->GetBufferSize());
fBytesRead += nr;
fReadCalls++;
#ifdef WIN32
SetFileBytesRead(GetFileBytesRead() + nr);
SetFileReadCalls(GetFileReadCalls() + 1);
#else
fgBytesRead += nr;
fgReadCalls++;
#endif
if (gPerfStats) {
fOffset = pos[0];
gPerfStats->FileReadEvent(this, pos[nbuf-1]+len[nbuf-1]-pos[0], start);
}
if (gMonitoringWriter)
gMonitoringWriter->SendFileReadProgress(this);
return kFALSE;
}
if (gDebug > 1)
Info("ReadBuffers", "XrdClient->ReadV failed, executing TFile::ReadBuffers");
if (buf && nbuf)
return TFile::ReadBuffers(buf, pos, len, nbuf);
else return kTRUE;
}
Bool_t TXNetFile::WriteBuffer(const char *buffer, Int_t bufferLength)
{
if (IsZombie()) {
Error("WriteBuffer", "WriteBuffer is not possible because object"
" is in 'zombie' state");
return kTRUE;
}
if (!fWritable) {
if (gDebug > 1)
Info("WriteBuffer","file not writable");
return kTRUE;
}
if (fIsRootd) {
if (gDebug > 1)
Info("WriteBuffer","Calling TNetFile::WriteBuffer");
return TNetFile::WriteBuffer(buffer, bufferLength );
}
if (!IsOpen()) {
Error("WriteBuffer","The remote file is not open");
return kTRUE;
}
Int_t st;
if ((st = WriteBufferViaCache(buffer, bufferLength))) {
if (st == 2)
return kTRUE;
return kFALSE;
}
if (!fClient->Write(buffer, fOffset, bufferLength)) {
if (gDebug > 0)
Info("WriteBuffer",
"error writing %d bytes of data wrote to offset %lld",
bufferLength , fOffset);
return kTRUE;
}
if (gDebug > 1)
Info("WriteBuffer", " %d bytes of data wrote to offset"
" %lld", bufferLength , fOffset);
fOffset += bufferLength;
fBytesWrite += bufferLength;
#ifdef WIN32
SetFileBytesWritten(GetFileBytesWritten() + bufferLength);
#else
fgBytesWrite += bufferLength;
#endif
return kFALSE;
}
void TXNetFile::Init(Bool_t create)
{
if (fInitDone) {
if (gDebug > 1)
Info("Init","TFile::Init already called once");
return;
}
if (fIsRootd) {
if (gDebug > 1)
Info("Init","rootd: calling directly TFile::Init");
return TNetFile::Init(create);
}
if (fClient) {
XrdSysMutexHelper m((XrdSysRecMutex *)fInitMtx);
if (fClient->IsOpen_wait()) {
if (gMonitoringWriter)
gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "rootinit", kFALSE);
bool usecachesave = fClient->UseCache(0);
TFile::Init(create);
fD = -2;
fClient->UseCache(usecachesave);
if (gMonitoringWriter)
gMonitoringWriter->SendFileOpenProgress(this, fOpenPhases, "endopen", kTRUE);
if (fClient->GetClientConn() && fClient->GetClientConn()->fRedirOpaque.length() <= 0) {
fEndpointUrl = fClient->GetClientConn()->GetCurrentUrl().GetUrl().c_str();
if (fEndpointUrl.GetPort() != fUrl.GetPort() ||
strcmp(fEndpointUrl.GetHostFQDN(), fUrl.GetHostFQDN()))
SetBit(TFile::kRedirected);
}
} else {
if (gDebug > 0)
Info("Init","open request failed!");
SafeDelete(fClient);
MakeZombie();
gDirectory = gROOT;
}
}
}
Bool_t TXNetFile::IsOpen() const
{
if (fIsRootd) {
if (gDebug > 1)
Info("IsOpen","Calling TNetFile::IsOpen");
return TNetFile::IsOpen();
}
if (!fClient)
return kFALSE;
return ((fClient && fInitDone) ? fClient->IsOpen() : kFALSE);
}
TFile::EAsyncOpenStatus TXNetFile::GetAsyncOpenStatus()
{
if (fAsyncOpenStatus != TFile::kAOSNotAsync) {
if (fClient->IsOpen_inprogress()) {
return TFile::kAOSInProgress;
} else {
if (fClient->IsOpen())
return TFile::kAOSSuccess;
else
return TFile::kAOSFailure;
}
}
return TFile::kAOSNotAsync;
}
Int_t TXNetFile::ReOpen(const Option_t *Mode)
{
if (fIsRootd) {
if (gDebug > 1)
Info("ReOpen","Calling TNetFile::ReOpen");
return TNetFile::ReOpen(Mode);
}
return TFile::ReOpen(Mode);
}
void TXNetFile::Close(const Option_t *opt)
{
if (fIsRootd) {
if (gDebug > 1)
Info("Close","Calling TNetFile::Close");
TNetFile::Close(opt);
return;
}
if (!fClient) return;
TFile::Close(opt);
fIsRootd = kFALSE;
if (IsOpen())
fClient->Close();
fD = -1;
}
void TXNetFile::Flush()
{
if (IsZombie()) {
Error("Flush", "Flush is not possible because object is"
" in 'zombie' state");
return;
}
if (!fWritable) {
if (gDebug > 1)
Info("Flush", "file not writable - do nothing");
return;
}
if (fIsRootd) {
if (gDebug > 1)
Info("Flush","Calling TNetFile::Flush");
TNetFile::Flush();
return;
}
if (!IsOpen()) {
Error("Flush","The remote file is not open");
return;
}
FlushWriteCache();
fClient->Sync();
if (gDebug > 1)
Info("Flush", "XrdClient::Sync called.");
}
Int_t TXNetFile::SysStat(Int_t fd, Long_t *id, Long64_t *size, Long_t *flags,
Long_t *modtime)
{
if (IsZombie()) {
Error("SysStat", "SysStat is not possible because object is"
" in 'zombie' state");
*size = 0;
return 1;
}
if (fIsRootd) {
if (gDebug > 1)
Info("SysStat", "calling TNetFile::SysStat");
return TNetFile::SysStat(fd, id, size, flags, modtime);
}
struct XrdClientStatInfo stinfo;
if (fClient && fClient->Stat(&stinfo)) {
*id = (Long_t)(stinfo.id);
*size = (Long64_t)(stinfo.size);
*flags = (Long_t)(stinfo.flags);
*modtime = (Long_t)(stinfo.modtime);
if (gDebug > 1)
Info("SysStat", "got stats = %ld %lld %ld %ld",
*id, *size, *flags, *modtime);
} else {
if (gDebug > 1) {
if (!IsOpen()) Info("SysStat", "could not stat remote file. Not opened.");
else
Info("SysStat", "could not stat remote file");
}
*id = -1;
return 1;
}
return 0;
}
Int_t TXNetFile::SysClose(Int_t fd)
{
if (IsZombie()) {
Error("SysClose", "SysClose is not possible because object is"
" in 'zombie' state");
return 0;
}
if (fIsRootd) {
if (gDebug > 1)
Info("SysClose","Calling TNetFile::SysClose");
return TNetFile::SysClose(fd);
}
if (IsOpen())
fClient->Close();
return 0;
}
Int_t TXNetFile::SysOpen(const char* pathname, Int_t flags, UInt_t mode)
{
if (fIsRootd) {
if (gDebug > 1)
Info("SysOpen", "Calling TNetFile::SysOpen");
return TNetFile::SysOpen(pathname, flags, mode);
}
if (!fClient) {
CreateXClient(fUrl.GetUrl(), fOption, fNetopt, kFALSE);
} else {
Open(fOption.Data(), kFALSE);
}
if (!IsOpen())
return -1;
return -2;
}
void TXNetFile::SetEnv()
{
TString allowRE = gEnv->GetValue("XNet.RedirDomainAllowRE", "");
if (allowRE.Length() > 0)
EnvPutString(NAME_REDIRDOMAINALLOW_RE, allowRE.Data());
TString denyRE = gEnv->GetValue("XNet.RedirDomainDenyRE", "");
if (denyRE.Length() > 0)
EnvPutString(NAME_REDIRDOMAINDENY_RE, denyRE.Data());
TString allowCO = gEnv->GetValue("XNet.ConnectDomainAllowRE", "");
if (allowCO.Length() > 0)
EnvPutString(NAME_CONNECTDOMAINALLOW_RE, allowCO.Data());
TString denyCO = gEnv->GetValue("XNet.ConnectDomainDenyRE", "");
if (denyCO.Length() > 0)
EnvPutString(NAME_CONNECTDOMAINDENY_RE, denyCO.Data());
Int_t connTO = gEnv->GetValue("XNet.ConnectTimeout",
DFLT_CONNECTTIMEOUT);
EnvPutInt(NAME_CONNECTTIMEOUT, connTO);
Int_t recoTO = gEnv->GetValue("XNet.ReconnectWait",
DFLT_RECONNECTWAIT);
if (recoTO == DFLT_RECONNECTWAIT) {
recoTO = gEnv->GetValue("XNet.ReconnectTimeout",
DFLT_RECONNECTWAIT);
}
EnvPutInt(NAME_RECONNECTWAIT, recoTO);
Int_t requTO = gEnv->GetValue("XNet.RequestTimeout",
DFLT_REQUESTTIMEOUT);
EnvPutInt(NAME_REQUESTTIMEOUT, requTO);
Int_t maxRedir = gEnv->GetValue("XNet.MaxRedirectCount",
DFLT_MAXREDIRECTCOUNT);
EnvPutInt(NAME_MAXREDIRECTCOUNT, maxRedir);
Int_t rAheadsiz = gEnv->GetValue("XNet.ReadAheadSize",
DFLT_READAHEADSIZE);
EnvPutInt(NAME_READAHEADSIZE, rAheadsiz);
Int_t rCachesiz = gEnv->GetValue("XNet.ReadCacheSize",
DFLT_READCACHESIZE);
EnvPutInt(NAME_READCACHESIZE, rCachesiz);
Int_t maxRetries = gEnv->GetValue("XNet.FirstConnectMaxCnt",
DFLT_FIRSTCONNECTMAXCNT);
EnvPutInt(NAME_FIRSTCONNECTMAXCNT, maxRetries);
Int_t parStreamsCnt = gEnv->GetValue("XNet.ParStreamsPerPhyConn",
DFLT_MULTISTREAMCNT);
EnvPutInt(NAME_MULTISTREAMCNT, parStreamsCnt);
Int_t tcpWindowSize = gEnv->GetValue("XNet.DfltTcpWindowSize",
DFLT_DFLTTCPWINDOWSIZE);
EnvPutInt(NAME_DFLTTCPWINDOWSIZE, tcpWindowSize);
Int_t transactionTimeout = gEnv->GetValue("XNet.TransactionTimeout",
DFLT_TRANSACTIONTIMEOUT);
EnvPutInt(NAME_TRANSACTIONTIMEOUT, transactionTimeout);
fgRootdBC = gEnv->GetValue("XNet.RootdFallback", 1);
EnvPutInt(NAME_KEEPSOCKOPENIFNOTXRD, fgRootdBC);
TString socks4Host = gEnv->GetValue("XNet.SOCKS4Host","");
Int_t socks4Port = gEnv->GetValue("XNet.SOCKS4Port",-1);
if (socks4Port > 0) {
if (socks4Host.IsNull())
socks4Host = "127.0.0.1";
EnvPutString(NAME_SOCKS4HOST, socks4Host.Data());
EnvPutInt(NAME_SOCKS4PORT, socks4Port);
}
const char *cenv = 0;
TString autolog = gEnv->GetValue("XSec.Pwd.AutoLogin","1");
if (autolog.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecPWDAUTOLOG")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecPWDAUTOLOG",autolog.Data());
TString netrc;
netrc.Form("%s/.rootnetrc",gSystem->HomeDirectory());
gSystem->Setenv("XrdSecNETRC", netrc.Data());
TString alogfile = gEnv->GetValue("XSec.Pwd.ALogFile","");
if (alogfile.Length() > 0)
gSystem->Setenv("XrdSecPWDALOGFILE",alogfile.Data());
TString verisrv = gEnv->GetValue("XSec.Pwd.VerifySrv","1");
if (verisrv.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecPWDVERIFYSRV")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecPWDVERIFYSRV",verisrv.Data());
TString srvpuk = gEnv->GetValue("XSec.Pwd.ServerPuk","");
if (srvpuk.Length() > 0)
gSystem->Setenv("XrdSecPWDSRVPUK",srvpuk.Data());
TString cadir = gEnv->GetValue("XSec.GSI.CAdir","");
if (cadir.Length() > 0)
gSystem->Setenv("XrdSecGSICADIR",cadir.Data());
TString crldir = gEnv->GetValue("XSec.GSI.CRLdir","");
if (crldir.Length() > 0)
gSystem->Setenv("XrdSecGSICRLDIR",crldir.Data());
TString crlext = gEnv->GetValue("XSec.GSI.CRLextension","");
if (crlext.Length() > 0)
gSystem->Setenv("XrdSecGSICRLEXT",crlext.Data());
TString ucert = gEnv->GetValue("XSec.GSI.UserCert","");
if (ucert.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERCERT",ucert.Data());
TString ukey = gEnv->GetValue("XSec.GSI.UserKey","");
if (ukey.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERKEY",ukey.Data());
TString upxy = gEnv->GetValue("XSec.GSI.UserProxy","");
if (upxy.Length() > 0)
gSystem->Setenv("XrdSecGSIUSERPROXY",upxy.Data());
TString valid = gEnv->GetValue("XSec.GSI.ProxyValid","");
if (valid.Length() > 0)
gSystem->Setenv("XrdSecGSIPROXYVALID",valid.Data());
TString deplen = gEnv->GetValue("XSec.GSI.ProxyForward","0");
if (deplen.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecGSIPROXYDEPLEN")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecGSIPROXYDEPLEN",deplen.Data());
TString pxybits = gEnv->GetValue("XSec.GSI.ProxyKeyBits","");
if (pxybits.Length() > 0)
gSystem->Setenv("XrdSecGSIPROXYKEYBITS",pxybits.Data());
TString crlcheck = gEnv->GetValue("XSec.GSI.CheckCRL","1");
if (crlcheck.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecGSICRLCHECK")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecGSICRLCHECK",crlcheck.Data());
TString delegpxy = gEnv->GetValue("XSec.GSI.DelegProxy","0");
if (delegpxy.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecGSIDELEGPROXY")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecGSIDELEGPROXY",delegpxy.Data());
TString signpxy = gEnv->GetValue("XSec.GSI.SignProxy","1");
if (signpxy.Length() > 0 &&
(!(cenv = gSystem->Getenv("XrdSecGSISIGNPROXY")) || strlen(cenv) <= 0))
gSystem->Setenv("XrdSecGSISIGNPROXY",signpxy.Data());
gSystem->IgnoreSignal(kSigPipe);
}
void TXNetFile::SynchronizeCacheSize()
{
if (fClient == 0) return;
fClient->UseCache(TRUE);
Int_t size;
Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
Float_t missrate, bytesusefulness;
int newbsz = -1;
if (fClient->GetCacheInfo(size, bytessubmitted,
byteshit, misscount,
missrate, readreqcnt,
bytesusefulness) ) {
TFileCacheRead *cacheRead = GetCacheRead();
if (cacheRead) {
newbsz = GetBufferSize() / 2 * 3;
newbsz = TMath::Max(newbsz, size);
} else {
newbsz = size;
}
}
if (newbsz > 0)
fClient->SetCacheParameters(newbsz, 0, XrdClientReadCache::kRmBlk_FIFO);
}
void TXNetFile::ResetCache()
{
if (fClient)
fClient->RemoveAllDataFromCache();
}
Int_t TXNetFile::GetBytesToPrefetch() const
{
Int_t size;
Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
Float_t missrate, bytesusefulness;
Int_t bytes = 0;
if (fClient && fClient->GetCacheInfo(size, bytessubmitted,
byteshit, misscount,
missrate, readreqcnt,
bytesusefulness) )
bytes = size;
return ((bytes < 0) ? 0 : bytes);
}
void TXNetFile::Print(Option_t *option) const
{
Printf("TXNetFile caching information:");
Int_t size;
Long64_t bytessubmitted, byteshit, misscount, readreqcnt;
Float_t missrate, bytesusefulness;
if (fClient && fClient->GetCacheInfo(size, bytessubmitted,
byteshit, misscount,
missrate, readreqcnt,
bytesusefulness)) {
Printf(" Max size: %d", size);
Printf(" Bytes submitted: %lld", bytessubmitted);
Printf(" Bytes hit (estimation): %lld", byteshit);
Printf(" Miss count: %lld", misscount);
Printf(" Miss rate: %f", missrate);
Printf(" Read requests count: %lld", readreqcnt);
Printf(" Bytes usefulness: %f\n", bytesusefulness);
} else
Printf(" -- No Xrd client instance allocated --\n");
TFile::Print(option);
}